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'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);
Related
I need LPOLESTR (Long Pointer OLE String) as an argument to a simple function call.
According to The Complete Guide to C++ Strings, Part II - String Wrapper Classes
OLECHAR is a Unicode character (wchar_t)
LPOLESTR is a string of OLECHAR (OLECHAR*)
So I should be able to do this:
int demo(LPOLESTR ptName) {
return 1;
}
int main(){
demo(L"Visible");
}
But I'm getting a compile error:
(const wchar_t[8])L"Visible"
argument of type "const wchar_t *" is incompatible with parameter of type "LPOLESTR"
or maybe I'll try a variable:
LPOLESTR lVis = L"Visible";
But I get this compiler error:
(const wchar_t[8])L"Visible"
a value of type "const wchar_t *" cannot be used to initialize an entity of type "LPOLESTR"
I have #include <string> at the top.
This seems like it should be a simple thing but I've been Googling all morning and can't find the answer. How do I create a variable or constant of type LPOLESTR in C++?
The problem you have is that LPOLESTR is a typedef for wchar_t*.
A compiler will not allow you to convert a const wchar_t* to a wchar_t* without an explicit const_cast.
Writing, using an alternative type LPCOLESTR:
LPCOLESTR lVis = L"Visible";
will fix the immediate compilation error as would the more Windows-like and probably preferred by Windows programmers.
Using a const_cast is, in general, not advisable but you will get away with it if the function documentation states that it does not attempt to modify the data passed to it.
When I compile in Visual Studio 2022 and by using standard C++20, I get similar error messages.
*Error (active) E0167 argument of type "const wchar_t *" is incompatible with parameter of type "LPOLESTR"*
I needed to pass through the compilation by avoiding "strict const-qualification" conformance by using compiler option "/Zc:strictStrings-"
Project Properties | C/C++ | Command Line -- add the compiler option.
I have the following code line:
typedef P2FUNC(Std_ReturnType, APP1, GetData) (P2VAR(max_data, AUTOMATIC, APP2)
whereby P2FUNC and P2VAR is a compiler Macro:
#define P2FUNC(rettype, ptrclass, fctname) rettype (*fctname)
#define P2VAR(ptrtype, memclass, ptrclass) ptrtype *
and max_data is defined as:
typedef uint8 max_data[];
The compiler gives me the following error:
error: parameter '<anonymous>' includes pointer to array of unknown bound 'max_data {aka unsigned char []}'
This .h files is included within a .cpp file within an extern"C"{ ...declaration.
My question now is, it is possible to disable this error message for this specific case? According some specific standard, this situation has it's own reason regarding the undetermined size of array.
I'm compiling with g++ compiler.
Will be thankful for help.
When you pass arrays to functions, arrays gets implicitily converted to pointers, and you can't create pointers to array of unknown size.
To solve your issue, either give a size to your array typedef uint8 max_data[10]; or use pointers and dynamic memory allocation.
Try defining max_data as:
typedef uint8* max_data;
of specify a size:
typedef uint8 max_data[10];
I am trying to build an old binutils (2.13). getting the error ./config/obj-elf.c:364: error: invalid type argument of ‘->’ (have ‘int’) on the next line :
if (symbol_get_obj (symbolP)->local)
{...
the function symbol_get_obj :
OBJ_SYMFIELD_TYPE *
symbol_get_obj (s)
symbolS *s;
{
if (LOCAL_SYMBOL_CHECK (s))
s = local_symbol_convert ((struct local_symbol *) s);
return &s->sy_obj;
}
OBJ_SYMFIELD_TYPE is defined to be :
#define OBJ_SYMFIELD_TYPE struct elf_obj_sy
and elf_obj_sy is
struct elf_obj_sy
{
/* Whether the symbol has been marked as local. */
int local;
/* Use this to keep track of .size expressions that involve
differences that we can't compute yet. */
expressionS *size;
/* The name specified by the .symver directive. */
char *versioned_name;
#ifdef ECOFF_DEBUGGING
/* If we are generating ECOFF debugging information, we need some
additional fields for each symbol. */
struct efdr *ecoff_file;
struct localsym *ecoff_symbol;
valueT ecoff_extern_size;
#endif
};
couldn't understand what is wrong with this code ... any advice ?
Based on the error message, one possible reason is that the declaration of the function symbol_get_obj fails to appear before the place you call it, which makes the return value default to type int, an invalid type for operator ->. You might want to check this. Make sure the correct presence of symbol_get_obj's declaration through header file inclusion or explicit function prototype.
invalid type argument of ‘->’ (have ‘int’)
That can only make sense if
symbol_get_obj(symbolP)
returns int. Which it does not.
So, the only logical conclusion is that symbol_get_obj has not been declared at the point in the code where the error occurs. In which case the compiler will assume that it is a function that returns a value of type int. Which would then explain the error message.
When the following bit of code is compiled with the diab c++ compiler (dplusplus), it generates a conversion warning on the third line. It can be resolved by casting the result of the (&&) operator to anything other than bool.
Code:
bool first = 1;
bool second = 1;
bool ret = (first && second); //generates compile warning
Error:
warning: (etoa:1643): narrowing or signed-to-unsigned type conversion
found: int to unsigned char
I verified that nothing is defining bool to another type. Does this look like a compiler issue, or is there something else I might be missing that could cause this?
Wind River's web site indicates that the Diab compiler can compile either C or C++.
In C, the && operator yields a result of type int, with the value 0 or 1. That's consistent with the warning you're seeing.
As of the 1990 ISO standard, C did not have a built-in bool type. It was common to define bool as a typedef. It appears from the message that bool is a typedef for unsigned char, probably in some header. The 1999 ISO C standard adds a new predefined boolean type called _Bool; the identifier bool is defined in <stdbool.h> as a macro that expands to _Bool. But if <stdbool.h> isn't included, bool can be defined in some other way.
In C++, && yields a result of type bool with the value false or true, and bool is a distinct fundamental type. This has been the case at least since the 1998 ISO C++ standard.
I strongly suspect you're getting this warning because you're compiling your code as C rather than as C++. A less likely possibility is that the Diab compiler doesn't fully conform to the C++ standard; it might have a way to tell it to conform more closely.
I haven't used the Diab compiler. Typically you can control the language being compiled by using a particular file extension (typically .c for C and .cpp for C++), or by using a different command, or both.
Consult the compiler's documentation to find out how to invoke it as a conforming C++ compiler.
As an experiment, before changing the way you invoke the compiler, you might try adding a declaration:
int class;
to your source file. This is legal in C, but a syntax error in C++ (since class is a C++ keyword).
UPDATE:
The OP says he's definitely compiling as C++, not as C. But the warning message implies that && yields int, and that bool is the same type as unsigned char.
A warning doesn't directly indicate that the compiler is not conforming; compilers can warn about anything they like. But the content of this warning does suggest a compiler bug, or at least a compiler that doesn't conform to any C+
Any conforming C++ compiler must produce diagnostics for this program. What does your compiler do? (Please don't add any #include directives.)
int main() {
class dummy { }; // Just to make sure it's C++
bool b;
unsigned char c;
bool* pb = &c; // Invalid conversion
unsigned char* pc = &b; // Invalid conversion
}
And what output do you get when you compile and execute this program?
#include <iostream>
int main() {
std::cout << "__cplusplus = " << __cplusplus << "\n";
}
Clearly casting between function pointers and object pointers is undefined behaviour in the general sense, but POSIX (see: dlsym) and WinAPI (see: GetProcAddress) require this.
Given this, and given the fact that such code is targeting a platform-specific API anyway, its portability to platforms where function pointers and object pointers aren't compatible is really irrelevant.
But -Wpedantic warns about it anyway, and #pragma GCC diagnostic ignored "-Wpedantic" has no effect:
warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object [enabled by default]
I want to keep -Wpedantic enabled, since it does give good warnings, but I don't want to have real warnings and errors lost amidst a sea of irrelevant warnings about function pointer to object pointer casts.
Is there a way to accomplish this?
Running GCC 4.8.0 on Windows (MinGW):
gcc (rubenvb-4.8.0) 4.8.0
CODE SAMPLE
#include <windows.h>
#include <iostream>
int main (void) {
std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),"five")) << std::endl;
}
Emits (with -Wpedantic):
warning_demo.cpp: In function 'int main()':
warning_demo.cpp:7:87: warning: ISO C++ forbids casting between pointer-to-funct
ion and pointer-to-object [enabled by default]
std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),
"five")) << std::endl;
^
I think you could use g++'s system_header directive here:
wrap_GetProcAddress.h:
#ifndef wrap_GetProcAddress_included
#define wrap_GetProcAddress_included
#pragma GCC system_header
template <typename Result>
Result GetProcAddressAs( [normal parameters] )
{
return reinterpret_cast<Result>(GetProcAddressAs( [normal parameters] ));
}
#endif
This works fine.
template <typename RESULT, typename ...ARGS>
void * make_void_ptr(RESULT (*p)(ARGS...)) {
static_assert(sizeof(void *) == sizeof(void (*)(void)),
"object pointer and function pointer sizes must equal");
void *q = &p;
return *static_cast<void **>(q);
}
There's always the memcpy trick you can use:
int (*f)() = 0;
int *o;
memcpy(&o, &f, sizeof(int*));
You can see it on ideone: m is generating warnings, while g is OK.
As to other course of action you might want to take: One obvious possibility would be to "fix" the header defining dlsym to actually return a function pointer (like void (*)()). Good luck with that.