Библиотека переопределяет NULL
-
08-07-2019 - |
Вопрос
Я работаю с библиотекой, которая переопределяет NULL. Это вызывает некоторые проблемы с другими частями моей программы. Я не уверен, что я могу с этим поделать. Любая идея? Моя программа на C ++, библиотека на C .
#ifdef NULL
#undef NULL
#endif
/**
* NULL define.
*/
#define NULL ((void *) 0)
О, и он выдает эти ошибки:
Generic.h:67: error: default argument for parameter of type 'LCD::LCDBase*' has type 'void*'
Generic.cpp: In constructor 'LCD::Generic::Generic(std::string, Json::Value*, int, LCD::LCDBase*)':
Generic.cpp:44: error: invalid conversion from 'void*' to 'QObject*'
Generic.cpp:44: error: initializing argument 2 of 'LCD::LCDWrapper::LCDWrapper(LCD::LCDInterface*, QObject*)'
Generic.cpp: In member function 'void LCD::Generic::BuildLayouts()':
Generic.cpp:202: error: invalid conversion from 'void*' to 'LCD::Widget*'
Generic.cpp: In member function 'void LCD::Generic::AddWidget(std::string, unsigned int, unsigned int, std::string)':
Generic.cpp:459: error: invalid conversion from 'void*' to 'LCD::Widget*'
scons: *** [Generic.o] Error 1
Вот первый:
Generic(std::string name, Json::Value *config, int type, LCDBase *lcd = NULL);
Редактировать. Хорошо, приведение в явном виде работает, но как преобразовать указатель на функцию?
Решение
Можете ли вы перестроить библиотеку без этого определения? Это то, что я попробую в первую очередь. NULL
- довольно стандартный макрос, и предполагается, что он определен везде.
В данный момент ваша проблема в том, что C ++ не разрешает автоматическое приведение из void *
к другим типам указателей, как это делает C.
Из Справочника по C ++ :
В C ++ NULL расширяется до 0 или 0L.
Если это не сработает, просто выполните глобальную замену в библиотеке: NULL
на LIBDEFINEDNULL
или что-то в этом роде. Таким образом вы сохраните код библиотеки и избежите столкновения макросов.
Другие советы
У вас есть доступ к этому источнику библиотек? Если это так, я думаю, что поиск и замена по их коду в порядке. (Замените их NULL на LIBNAME_NULL или что-то подобное.) Если это просто не вариант, я бы рекомендовал использовать 0 в вашем коде вместо NULL.
Мне любопытно: какие проблемы это вызывает? Они не изменяют значение null, только приведение по умолчанию.
В одном из ваших комментариев говорится, что вы рассматривали возможность его переопределения самостоятельно, но не знаете, к чему его переопределить.
Многие реализации будут определять NULL следующим образом:
#undef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void*)0)
#endif
Это потому, что в C имеет смысл иметь его как пустой указатель, потому что это тип указателя, который можно неявно приводить к другим типам.
C ++ не разрешает этого (что вызывает ваши проблемы), но использование 0
вместо NULL
работает.
Я думаю, что во всех последних версиях GCC определит его как __ null
, которое является непереносимым расширением.
Наиболее общий подход заключается в том, чтобы обернуть оскорбительные включения, сохранить и восстановить предыдущее определение макроса. Это, однако, зависит от компилятора.
Вот как вы могли бы сделать это с VC:
#pragma push_macro("NULL")
#include <offendinglib.h>
#pragma pop_macro("NULL")
В качестве альтернативы, установите макрос таким, каким он должен быть после вас:
#include <offendinglib.h>
#undef NULL
#define NULL 0
Да, вам просто нужно правильно разыграть:
Generic(std::string name, Json::Value *config, int type,
LCDBase *lcd = (LCDBase *)NULL);