I'm working with a library that redefines NULL. It causes some problems with other parts of my program. I'm not sure what I can do about it. Any idea? My program'开发者_StackOverflow社区s in C++, the library's in C.
#ifdef NULL
#undef NULL
#endif
/**
* NULL define.
*/
#define NULL ((void *) 0)
Oh, and it produces these errors:
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
Here's the first one:
Generic(std::string name, Json::Value *config, int type, LCDBase *lcd = NULL);
Edit: Ok, casting explicitly works, but how do I cast for a function pointer?
Can you rebuild the library without that define? That's what I'd try first. NULL
is a pretty standard macro, and should be assumed to be defined everywhere.
Right now, your problem is that C++ doesn't allow automatic casts from void *
to other pointer types like C does.
From C++ Reference:
In C++, NULL expands either to 0 or 0L.
If that doesn't work, just do a global replace in the library: NULL
to LIBDEFINEDNULL
or something. That way you'll keep the library code intact and avoid the macro collision.
Do you have access to that libraries source? If so, I think a search and replace on their code is in order. (Replace their NULL with LIBNAME_NULL or something similar.) If that's simply not an option then I would recommend using 0 in your code instead of NULL.
I'm curious, though: What problems is that causing? They're not changing the value of null, only the default casting.
One of your comments says you've considered redefining it yourself, but you don't know what to redefine it to.
A lot of implementations will define NULL like this:
#undef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void*)0)
#endif
This is because in C, it makes sense to have it as a void pointer, because it's a pointer type that can be implicitly cast to other types.
C++ doesn't allow this (which is causing your problems), but using 0
instead of NULL
works.
I think in all recent versions, GCC will actually define it to __null
, which is a non-portable extension.
The most generic approach would be to wrap up the offending includes and store and restore the macros previous definition. This, however, is compiler-dependent.
This is how you could do it with VC:
#pragma push_macro("NULL")
#include <offendinglib.h>
#pragma pop_macro("NULL")
Alternatively, set the macro to what you need it to be afterwards:
#include <offendinglib.h>
#undef NULL
#define NULL 0
Yes, you do just need to cast appropriately:
Generic(std::string name, Json::Value *config, int type,
LCDBase *lcd = (LCDBase *)NULL);
精彩评论