I am developing a multi-platform application and in one component I have a class method called DrawText. Unfortunately, I get a linker error (on windows only) saying that there is an unresolved external symbol for a DrawTextW method of this class.
I've seen this before with other methods ending in "Text" where it is looking for either a FooTextW or FooTextA method instead of the FooText method I defined. My assumption is that somewhere in the Windows headers there is a macro definition assigning FooText to FooTextW or FooTextA based on some other definition.
Aside from renaming my function (which is what I did in the past), does anybody have any good ideas for getting around this issue?
Thanks.
Joe
You really only have two choices:
#ifdef DrawText
#undef DrawText
#endif
Or rename your function. Win32 uses macros which have no namespacing or scoping, so you're kinda stuck.
We just re-name our functions.
BTW: It's based on #ifdef UNICODE usually (or _UNICODE or a few other variants).
Yes, this is a real problem with using Windows, and there's no way to turn it off since the headers all look like this:
#ifdef UNICODE
#define GetDlgItemText GetDlgItemTextW
#else
#define GetDlgItemText GetDlgItemTextA
#endif
So you're going to get the symbol defined either way. It would be very nice if you could #define something before #include'ing windows.h that turns this behavior off, but alas none exists.
Related
I'm working on existing C++ code, which is using a kind of API.
While browsing the code I found a strange syntax that I saw now for the first time and I can't figure out what it does or how such is called.
It goes like this:
class KINDA_API foobar : public foo {
// Some class declarations
};
Everything after foobar is understandable for me. But what means that KINDA_API? What does this do? Is that any kind of advanced derivation or something like that?
Maybe there is any other Thread that answers this, and I also searched for it, but I don't even know how this is called ^^'
Usually when you see OMGWFT_API declarations in this exact way, this is a 'magic switch' for building a library in correct "mode":
static linking - OMGWFT_API replaced by "" (empty string)
dynamic linking - DLL - OMGWFT_API replaced by declspec(dllexport)
dynamic linking - EXE - OMGWFT_API replaced by declspec(dllimport)
i.e.
#ifdef BUILD_ME_AS_STATICLIB
#define OMGWFT_API
#else
#ifdef BUILD_ME_AS_DLL
#define OMGWFT_API declspec(dllexport)
#else
#define OMGWFT_API declspec(dllimport)
#endif
#endif
This is of course just an sketch of example, but I think you get the point now. Keywords are taken from MSVC not GCC< because I accidentially happen to remember them.
The "BUILD_ME_AS...." macros would be then defined via project options or -D command line switch.
However, it the OMGWFT_API can be set to have any meaning, so be sure to grep/search for a #define that sets this.
I guess it is a #define-d macro that does some "magic" before compile.
If you look through the existing call you are likely to find somthing like:
#ifdef _WIN32
#define KINDA_API <windows specific attribute>
#elif __linux
#define KINDA_API <linux specific attribute>
etc...
These macros are more likely conditioned on compilers and/or their versions rather than operating system but you get the idea...
Just caught a silly bug. I have a zip processing library with a CreateFile() function in it. Winbase.h, included somewhere deep in my headers, redefines it as CreateFileW and linker goes nuts.
Of course I will exclude winbase in this particular case. It just shouldn't be in the scope in the first place. But the theoretical question is still interesting,
Is there a way to suppress some defines locally?
You can get around the macro by putting parentheses around the name:
(CreateFile)(arguments);
This works because the macro CreateFile is a function-like macro (i.e. it takes a list of arguments in parentheses); the right parenthesis after the name doesn't match the syntax for using a function-like macro, so the preprocessor does not expand it.
Of course, the "right" solution is to name the function properly, i.e., create_file. <g>
Removing the offending header file is ALWAYS the best solution for this (especially one as large as windows.h or winbase.h - they are included far too freely for my taste in many projects).
The only other solution is #undef offending_symbol.
Of course, another important thing is "do not use names that match the Windows/Linux system call names" - but CreateFile is a very obvious name for a function that creates a file, so I can see the temptation.
Preprocessor macros have no notion of C++ scope. #defines are just text replacements. If you want to have a 'local' #define, you do something like this:
#define CreateFileW CreateFile
... // here I can use the macro
#undef CreateFileW
Or in your case
#undef CreateFileW
... // Here the macro is not available
#define CreateFileW CreateFile
There is
#undef
which removes defines (but nothing else).
Apart from the aforementioned #undef there technically is not much you can do against #defines, at least not portably.
The best way is to not use #define at all, or at least as little as possible and as constrained as possible. Sometimes you just need a macro to generate some boilerplate code a few times. Be sure to #undef that macro once you are done. The only other valid applications of #define I can think of are include guards and flags for conditional preprocessing.
For #define-deseases like the WinAPI headers you just should constrain them as much as possible. Don't use the #defined types of that API in your headers. You almost never want to use an API all over your application, so use it only in the cpps of a small layer around the API. Reducing the dependencies that way gives a lot more than just disinfecting the rest of your code.
What I'm talking about is to find a way to avoid the macros in <windows.h> from polluting whatever project I'm writing.
Excerpts from windows.h:
#ifdef UNICODE
#define LoadImage LoadImageW
#else
#define LoadImage LoadImageA
#endif // !UNICODE
#ifdef UNICODE
#define GetMessage GetMessageW
#else
#define GetMessage GetMessageA
#endif // !UNICODE
The majority of macros (over 99%) I'm okay with, but some of them I just couldn't find a way to avoid.
My idea is that since I always qualify the functions calls in my particular framework, e.g. ImageTool::LoadImage, Visual Studio should have enough clue that I'm not referencing the Windows API, which are all in the root namespace, i.e. ::LoadImage. But the MACRO system does not seem to be that smart.
Is there a compiler or preprocessor option that will just enable that?
Macro substitution are basically simple textual replacements, done before the proper compiler even starts to parse the code. Therefore they are not aware of namespaces or any other parts of the C++ syntax above the pure lexical level.
The straight forward way to avoid replacement of your identifiers is to remove the macros:
#ifdef LoadImage
#undef LoadImage
#endif
This of course will also stop following code from accessing the Windows API with the name LoadImage.
You will to live with it - you cannot avoid these macros on Windows platform. There is no macro-name-spacing in C/C++ pre-processor world. You may however, have all of your code defined and implemented before including any windows header - but that's wouldn't be possible, I believe.
I have some C++ code that includes a method called CreateDirectory(). Previously the code only used STL and Boost, but I recently had to include <windows.h> so I could look-up CSIDL_LOCAL_APPDATA.
Now, this code:
filesystem.CreateDirectory(p->Pathname()); // Actually create it...
No longer compiles:
error C2039: 'CreateDirectoryA' : is not a member of ...
Which corresponds to this macro in winbase.h:
#ifdef UNICODE
#define CreateDirectory CreateDirectoryW
#else
#define CreateDirectory CreateDirectoryA
#endif // !UNICODE
The pre-processor is redefining my method call. Is there any possible way to avoid this naming collision? Or do I have to rename my CreateDirectory() method?
You will be better off if you just rename your CreateDirectory method. If you need to use windows APIs, fighting with Windows.h is a losing battle.
Incidently, if you were consistent in including windows.h, this will still be compiling. (although you might have problems in other places).
You could create a module whose sole purpose is to #include <windows.h> and look up CSIDL_LOCAL_APPDATA wrapped in a function.
int get_CSIDL_LOCAL_APPDATA(void)
{
return CSIDL_LOCAL_APPDATA;
}
btw, Well done for working out what happened!
#undef CreateDirectory
As a developer working on a cross platform codebase, this is a problem. The only way to deal with it is to
ensure that windows.h is - on Windows builds at least - universally included. Then the CreateDirectory macro is defined in every one of your compilation units and is universally substituted with CreateDirectoryW. Precompiled headers are ideal for this
OR, if that is an unpleasant proposition, (and it is for me)
isolate windows.h usage into windows specific utility files. Create files that export the basic required functionality. The header files must use data types that are compatible with, but do NOT depend on the inclusion of windows.h. The cpp implementation file must (obviously) use windows.h.
If your utlility functions need to include project header files with conflicting symbols then the following pattern is a necessity:
#include <windows.h>
#ifdef CreateDirectory
#undef CreateDirectory
#endif
// etc
#include "some_class_with_CreateDirectory_method.h"
// ...
You will need to then explicitly call the non macro version of any windows api functions you have #undef'd - CreateDirectoryA or W etc.
push macro, undef it and pop the macro again:
#pragma push_macro("CreateDirectory")
#undef CreateDirectory
void MyClass::CreateDirectory()
{
// ...
}
#pragma pop_macro("CreateDirectory")
You can take a back up of CreateDirectory, then undefine it, and then define it again when you finish your job with you custom one.
#ifdef CreateDirectory
#define CreateDirectory_Backup CreateDirectory
#undef CreateDirectory
#endif
// ...
// Define and use your own CreateDirectory() here.
// ...
#ifdef CreateDirectory_Backup
#define CreateDirectory CreateDirectory_Backup
#undef CreateDirectory_Backup
#endif
Note that name conflict usually comes from a certain header file being included. Until then stuff like CreateDirectory and GetMessage isn't pulled into visibility and code compiles without a problem.
You can isolate such an inclusion into a wrapper header file and "#undef whatever" at its end. Then, whatever name collision you have will be gone. Unless, of course, you need to use those macros in your own code (yeah, so very likely...)
#pragma push_macro("CreateDirectory")
If nothing works, instead of renaming you could use your own namespace for your functions.
I am using both the JUCE Library and a number of Boost headers in my code. Juce defines "T" as a macro (groan), and Boost often uses "T" in it's template definitions. The result is that if you somehow include the JUCE headers before the Boost headers the preprocessor expands the JUCE macro in the Boost code, and then the compiler gets hopelessly lost.
Keeping my includes in the right order isn't hard most of the time, but it can get tricky when you have a JUCE class that includes some other classes and somewhere up the chain one file includes Boost, and if any of the files before it needed a JUCE include you're in trouble.
My initial hope at fixing this was to
#undef T
before any includes for Boost. But the problem is, if I don't re-define it, then other code gets confused that "T" is not declared.
I then thought that maybe I could do some circular #define trickery like so:
// some includes up here
#define ___T___ T
#undef T
// include boost headers here
#define T ___T___
#undef ___T___
Ugly, but I thought it may work.
Sadly no. I get errors in places using "T" as a macro that
'___T___' was not declared in this scope.
Is there a way to make these two libraries work reliably together?
As greyfade pointed out, your ___T___ trick doesn't work because the preprocessor is a pretty simple creature. An alternative approach is to use pragma directives:
// juice includes here
#pragma push_macro("T")
#undef T
// include boost headers here
#pragma pop_macro("T")
That should work in MSVC++ and GCC has added support for pop_macro and push_macro for compatibility with it. Technically it is implementation-dependent though, but I don't think there's a standard way of temporarily suppressing the definition.
Can you wrap the offending library in another include and trap the #define T inside?
eg:
JUICE_wrapper.h:
#include "juice.h"
#undef T
main.cpp:
#include "JUICE_wrapper.h"
#include "boost.h"
rest of code....
I then thought that maybe I could do some circular #define trickery like so:
The C Preprocessor doesn't work this way. Preprocessor symbols aren't defined in the same sense that a symbol is given meaning when, e.g., you define a function.
It might help to think of the preprocessor as a text-replace engine. When a symbol is defined, it's treated as a straight-up text-replace until the end of the file or until it's undefined. Its value is not stored anywhere, and so, can't be copied. Therefore, the only way to restore the definition of T after you've #undefed it is to completely reproduce its value in a new #define later in your code.
The best you can do is to simply not use Boost or petition the developers of JUCE to not use T as a macro. (Or, worst case, fix it yourself by changing the name of the macro.)