tags:

views:

57

answers:

2

Hi,

In my project I have a function named GetObject that is wrapped in one of my classes in my static library. When I call the function in another project that is using my library, I got this error:

Error 1 error LNK2019: unresolved external symbol "public: class hamur::HamurObject * __thiscall hamur::HamurWorld::GetObjectA(class std::basic_string,class std::allocator > const &)" (?GetObjectA@HamurWorld@hamur@@QAEPAVHamurObject@2@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "public: virtual void __thiscall MainState::Draw(void)" (?Draw@MainState@@UAEXXZ) MainState.obj

As I understand problem is GetObject is a preprocessor definition in "windows.h" and it becomes GetObjectA instead.

My question is:

I have never added "windows.h" header to any of my files. I am using SDL, Fmod, OpenGL. I have found that it comes from SDL_opengl.h

I have tried to use:

#ifdef GetObject
#undef GetObject
#endif

It worked out. Is it a good or only possible solution? I am trying to implement a library that should work in multi-platforms but I didn't test to compile it for any platform other than Windows, so I am now quite worried about porting. It would be very nice to have some advice before the things got worse for porting...

My current environment is Windows Xp - Visual Studio 2008.

Thanks in Advance

A: 

It will resolve the issue for Windows, however I recommend renaming your method to something more descriptive than GetObject in your codebase, as you may find similar conflicts with SetObject, etc. Additionally, you may actually want to use those Win32 APIs at some point, and the #undef will make that more tricky to do.

holtavolt
A: 

This is a perfect example of why using macros without any sort of library qualification (GetObject instead of WINDOWS_GetObject) is really stupid and a recipe for disaster. So, thanks for the example.

This should not be a problem on other platforms (finding this kind of macro nonsense is quite rare on implementations of UNIX). What you really should worry about is whether your project will still work if you change the header inclusion order on Windows and use a feature of SDL OpenGL after you include your header that contains the #undef. You might want to restore the value of GetObject at the end of your header file. Although I doubt it would be a problem on UNIX, I would suggest making it Windows-only:

// Your header file

#ifndef YOURHEADER_INCLUSION_GUARD
#define YOURHEADER_INCLUSION_GUARD

// ... your various includes ...

#ifdef OS_WINDOWS
#    ifdef GetObject
#        define MYPROJECT_MACRO_GETOBJECT_WAS_DEFINED
#    endif
#    undef GetObject
#endif

// ... the rest of your header ...

#ifdef OS_WINDOWS
#    if defined(MYPROJECT_MACRO_GETOBJECT_WAS_DEFINED)
#        undef MYPROJECT_MACRO_GETOBJECT_WAS_DEFINED
#        define GetObject GetObjectA
#    endif
#endif

#endif // End header inclusion guard

In your source file, you can afford to be a little sloppier with the macros, since you can control the header inclusion order in your source file and no one else is going to include your source file.

Michael Aaron Safyan
This still leads to problems when including this in the implementation file for the class or with anything that tries to call the `GetObject()` method.
Georg Fritzsche
@Georg, yes that is true. Perhaps the author should simply dump Windows? (Not using a name like "GetObject" is also a possibilty, but Windows is clearly the one at fault here).
Michael Aaron Safyan
Not that i have a perfect solution, but how about making it e.g. `#ifdef UNICODE #define WinApi_GetObject GetObjectW #else ...` if the function is needed instead of defining the problematic `GetObject` again?
Georg Fritzsche
Thanks guys. I think I will not go deep in intricacy further and simply will not use the name GetObject. Yes macros works very fine but as my aim is to write a multiplatform 2d game engine for everyone, I don't like to make same mistake as Windows did :) It works fine now but it could get clumsy when someone tries to do something with "windows.h" so that is not a generic solution I would like to achieve.
chaosmaker