Двойное подключение h файла
Есть сторонняя библиотека IRRemote для Arduino с таким заголовочным файлом IRremote.h
#ifndef IRremote_h
#define IRremote_h
.........
#include "IRremoteInt.h"
/*
* Include the sources here to enable compilation with macro values set by user program.
*/
#include "irReceive.cpp.h"
#include "irSend.cpp.h"
#include "IRremote.cpp.h"
#endif // IRremote_h
#pragma once
В irReceive.cpp.h есть такой код
IRrecv IrReceiver;
IRrecv::IRrecv() {
irparams.recvpin = 0; // 44 строка
irparams.blinkflag = false;
}
Теперь использование.
В своем main.cpp пишу
#include <IRremote.h>
#include "Controller.h"
......
Все компилируется без ошибок. Но если я в Controller.h тоже добавлю инклуд
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <IRremote.h>
#include "Settings.h"
class Controller {
.....
}
#endif //CONTROLLER_H
То получаю каскад ошибок линковки
CMakeFiles\Controller.dir\src\main.cpp.obj: In function
IRrecv::IRrecv():
C:\PROGRA~2\Arduino\LIBRAR~1\IRremote\src/irReceive.cpp.h:44: multiple definition ofIRrecv::IRrecv()
CMakeFiles\Controller.dir\src\Controller.cpp.obj:C:\PROGRA~2\Arduino\LIBRAR~1\IRremote\src/irReceive.cpp.h:44: first defined here
.........
CMakeFiles\Controller.dir\src\controller.cpp.obj: In functionIRrecv::IRrecv():
C:\PROGRA~2\Arduino\LIBRAR~1\IRremote\src/irReceive.cpp.h:44: multiple definition ofIRrecv::decode()
CMakeFiles\Controller.dir\src\AirConditionController.cpp.obj:C:\PROGRA~2\Arduino\LIBRAR~1\IRremote\src/irReceive.cpp.h:44: first defined here
Ошибок очень много, но все они ссылаются на одно место irReceive.cpp.h:44
Controller.h также инклудится в файл Controller.cpp, где находится реализация класса Controller
Как с этим бороться и откуда возникает эта ошибка? Ведь IRremote.h содержит include guard. Да, include guard не содержит файл irReceive.cpp.h, но он инклудится в одном месте в IRremote.h
Ответы (2 шт):
Вот этот код, о котором вы пишете -
IRrecv IrReceiver;
IRrecv::IRrecv() {
irparams.recvpin = 0; // 44 строка
irparams.blinkflag = false;
}
оказавшись дважды в разных .cpp-файлах, приводит к появлению объекта IrReceiver и конструктора в двух файлах. Линковщик не знает, какой выбрать.
Если у вас С++ не очень старый - вас спасет просто добавление слова inline перед каждым из них.
Если старый - то лучше не заморачиваться, а перенести это все в отдельный .cpp-файл в проекте. Это самое разумное решение - чтобы каждый занимался своим делом: заголовочный файл содержал заголовки-объявления, а файл реализации - содержал реализацию.
Оформил я баг-репорт. Если кто еще столкнется с этим багом в этой библиотеке, а баг все еще не закроют, то есть такой обходной путь:
- Вместо
IRremote.hнужно везде инклудитьIRremoteInt.h. В этом файле описаны все описания классов. - Ровно в одном cpp файле проекта пишем
#include <IRremote.h>. Тогда реализация подтягивается только один раз и проект компилируется.