Weird export macro behaviour.

This is a discussion on Weird export macro behaviour. within the Windows Programming forums, part of the Platform Specific Boards category; Hi, I've got a weird problem here. Well, I'm using a library and I use the usual macro definition: Code: ...

  1. #1
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476

    Weird export macro behaviour.

    Hi, I've got a weird problem here. Well, I'm using a library and I use the usual macro definition:

    Code:
    #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)  || defined( __MWERKS__)
    #   ifdef LIBRARY_EXPORT
    #      define DLL_EXPORT __declspec(dllexport)
    #   else
    #      define DLL_EXPORT  __declspec(dllimport)
    #   endif 
    #else
    #   ifdef LIBRARY_EXPORT
    #      define DLL_EXPORT __attribute__ ((visibility("default")))
    #   else
    #      define DLL_EXPORT
    #   endif 
    #endif
    for exporting. I put the LIBRARY_EXPORT in the pre-processor so it should've chosen the "# define DLL_EXPORT __declspec(dllexport)" line, right? But turns out it chooses the "# define DLL_EXPORT __declspec(dllimport)" or the else line. So I tried using some kind of hack like this:

    Code:
    #ifndef LIBRARY_EXPORT
    #define LIBRARY_EXPORT
    #endif
    
    #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)  || defined( __MWERKS__)
    ...
    And now the library can't be built at all. There are tons of LNK2001 and LNK2019 all over. Why does this happen? Please help because I'm still not that experienced using / developling with third party libraries.
    ERROR: Brain not found. Please insert a new brain!

    “Do nothing which is of no use.” - Miyamoto Musashi.

  2. #2
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,167
    Only the library must define LIBRARY_EXPORT. Any application that uses it must not. Otherwise you will get linking errors.
    But it would also help in posting what those errors are, as a start.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  3. #3
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    NOTE: This is the 3rd time that I've written because the board suggested that I've got to refresh the page before replying. Dammit. Why won't the board cache the message with a script so that it wasn't lost in the process? I'm so lazy rewriting the whole thing again.

    Ok, here goes my reply:

    Actually this happens when I'm trying to work with Delta3D, an open source engine. The original projects actually have the exporting preprocessor so they should be choosing #define DLL_EXPORT __declspec(dllexport) instead of #define DLL_EXPORT __declspec(dllimport), right? But I don't know why all of them just assume that it wasn't defined in the first place and choses the dllimport instead (or the "#else" block).

    I've been meddling with 2 of its base / core projects, dtUtil and dtCore. dtCore uses dtUtil as its dependency while dtUtil uses external pre compiled dependencies like Open Scene Graphe, ODE, xerces, etc.

    I've tried changing dtUtil/export.h:
    Code:
    #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)  || defined( __MWERKS__)
    #   ifdef DT_UTIL_LIBRARY
    #      define DT_UTIL_EXPORT __declspec(dllexport)
    #   else
    #      define DT_UTIL_EXPORT __declspec(dllexport)
    //#      define DT_UTIL_EXPORT __declspec(dllimport)
    #   endif 
    #else
    #   ifdef DT_UTIL_LIBRARY
    #      define DT_UTIL_EXPORT __attribute__ ((visibility("default")))
    #   else
    #      define DT_UTIL_EXPORT
    #   endif 
    #endif
    AND dtCore/export.h:
    Code:
    #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)  || defined( __MWERKS__)
    #   ifdef DT_CORE_LIBRARY
    #      define DT_CORE_EXPORT __declspec(dllexport)
    #   else
    #      define DT_CORE_EXPORT __declspec(dllexport)
    //#      define DT_CORE_EXPORT __declspec(dllimport)
    #   endif 
    #else
    #   ifdef DT_CORE_LIBRARY
    #      define DT_CORE_EXPORT __attribute__ ((visibility("default")))
    #   else
    #      define DT_CORE_EXPORT
    #   endif 
    #endif
    so that those two will be forced to use dllexport instead.

    FYI the DT_UTIL_LIBRARY and DT_CORE_LIBRARY are defined in their respective projects' preprocessor. But as you can see, they choose the "#else" block instead. Why does this happen?

    Without the hack, the library can actually be built just fine but using the hack, this happened: dtUtil can be built, but dtCore can't and displayed lots of LNK2001 and LNK2019 errors (up to 53 errors). These are a few of them:

    Code:
    Error	9	error LNK2001: unresolved external symbol "private: static class std::vector<class dtUtil::Enumeration *,class std::allocator<class dtUtil::Enumeration *> > dtUtil::BaseExceptionType::mGenericInstances" (?mGenericInstances@BaseExceptionType@dtUtil@@0V?$vector@PAVEnumeration@dtUtil@@V?$allocator@PAVEnumeration@dtUtil@@@std@@@std@@A)	shaderprogram.obj
    
    Error	10	error LNK2001: unresolved external symbol "private: static class std::vector<class dtUtil::Enumeration *,class std::allocator<class dtUtil::Enumeration *> > dtUtil::BaseExceptionType::mGenericInstances" (?mGenericInstances@BaseExceptionType@dtUtil@@0V?$vector@PAVEnumeration@dtUtil@@V?$allocator@PAVEnumeration@dtUtil@@@std@@@std@@A)	shaderxml.obj
    
    Error	11	error LNK2019: unresolved external symbol "private: static class std::vector<class dtUtil::Enumeration *,class std::allocator<class dtUtil::Enumeration *> > dtUtil::BaseExceptionType::mGenericInstances" (?mGenericInstances@BaseExceptionType@dtUtil@@0V?$vector@PAVEnumeration@dtUtil@@V?$allocator@PAVEnumeration@dtUtil@@@std@@@std@@A) referenced in function __unwindfunclet$??0?$has_slots@Vmulti_threaded_local@sigslot@@@sigslot@@QAE@XZ$0	singletonmanager.obj
    
    Error	12	error LNK2001: unresolved external symbol "private: static class std::vector<class dtUtil::Enumeration *,class std::allocator<class dtUtil::Enumeration *> > dtUtil::BaseExceptionType::mGenericInstances" (?mGenericInstances@BaseExceptionType@dtUtil@@0V?$vector@PAVEnumeration@dtUtil@@V?$allocator@PAVEnumeration@dtUtil@@@std@@@std@@A)	view.obj
    
    Error	33	error LNK2001: unresolved external symbol "private: static class std::vector<class dtUtil::Enumeration *,class std::allocator<class dtUtil::Enumeration *> > dtUtil::DateTime::TimeOrigin::mGenericInstances" (?mGenericInstances@TimeOrigin@DateTime@dtUtil@@0V?$vector@PAVEnumeration@dtUtil@@V?$allocator@PAVEnumeration@dtUtil@@@std@@@std@@A)	camera.obj
    
    Error	34	error LNK2019: unresolved external symbol "private: static class std::vector<class dtUtil::Enumeration *,class std::allocator<class dtUtil::Enumeration *> > dtUtil::DateTime::TimeOrigin::mGenericInstances" (?mGenericInstances@TimeOrigin@DateTime@dtUtil@@0V?$vector@PAVEnumeration@dtUtil@@V?$allocator@PAVEnumeration@dtUtil@@@std@@@std@@A) referenced in function "public: void __thiscall dtCore::Transform::GetTranslation(class osg::Vec3f &)const " (?GetTranslation@Transform@dtCore@@QBEXAAVVec3f@osg@@@Z)	environment.obj
    So what happened here? Thanks.
    ERROR: Brain not found. Please insert a new brain!

    “Do nothing which is of no use.” - Miyamoto Musashi.

  4. #4
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,167
    It seems that, if I understand this right, dtCore cannot find what it needs from dtUtil. dtCore needs to use dllimport for that, btw.
    I don't know if dtUtil is going to export anything, but the errors say the above.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  5. #5
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    Umm.. What do you mean? I'm lost here. Sorry, my experience with libraries is limited. It only consist of using pre-compiled libraries or making one huge application without separating it to modules using multiple libraries. I don't even know the difference between exporting or importing a library. Well I do understand a bit actually but not enough to make me understand how do they actually work. :P
    ERROR: Brain not found. Please insert a new brain!

    “Do nothing which is of no use.” - Miyamoto Musashi.

  6. #6
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,167
    Basically, to use something from a library, you need to do two things:
    1) The library must export what it wants others to use.
    2) The users must import what they want to use.
    So dtUtil needs to export the stuff that dtCore wants, and dtCore must import what dtUtil exports. dllimport is for import and dllexport is for export.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  7. #7
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    Umm.. I don't have any slightest idea. :P Thanks anyway. Gonna try googling for more info.
    ERROR: Brain not found. Please insert a new brain!

    “Do nothing which is of no use.” - Miyamoto Musashi.

  8. #8
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    You essentially create a define that determines whether or not a function is exported or imported. When compiling the DLL it should be set so the functions/classes are exported and when using the DLL it should not be set which causes the functions/classes to be imported.

    When you create a new DLL project in MSVC you will notice that it creates a define for you. If your project is called MyProject it will create MYPROJECT_EXPORTS. You then create this file:

    Code:
    #pragma once
    
    #ifdef MYPROJECT_EXPORTS
       #define MYPROJECT_DECL __declspec(dllexport)
    #else
       #define MYPROJECT_DECL __declspec(dllimport)
    #endif
    Then when you declare functions and/or classes you use this define. This is explained on MSDN quite nicely if you go and look for it.

    I have noticed a bug in 2008 where the pre-processor seems to get confused and the color highlighting is incorrect and highlights the wrong part of the #ifdef block. However even though the wrong define is highlighted it still internally is using the correct one.

  9. #9
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    Quote Originally Posted by Bubba View Post
    You essentially create a define that determines whether or not a function is exported or imported. When compiling the DLL it should be set so the functions/classes are exported and when using the DLL it should not be set which causes the functions/classes to be imported.

    When you create a new DLL project in MSVC you will notice that it creates a define for you. If your project is called MyProject it will create MYPROJECT_EXPORTS. You then create this file:

    Code:
    #pragma once
    
    #ifdef MYPROJECT_EXPORTS
       #define MYPROJECT_DECL __declspec(dllexport)
    #else
       #define MYPROJECT_DECL __declspec(dllimport)
    #endif
    Then when you declare functions and/or classes you use this define. This is explained on MSDN quite nicely if you go and look for it.

    I have noticed a bug in 2008 where the pre-processor seems to get confused and the color highlighting is incorrect and highlights the wrong part of the #ifdef block. However even though the wrong define is highlighted it still internally is using the correct one.
    OIC. That's why the macro for exporting / importing is defined on the pre-processor, not inside the source. Got it.

    Is it really a bug? Because I find it odd at first that the wrong block was highligthed.

    Thanks a lot guys.
    ERROR: Brain not found. Please insert a new brain!

    “Do nothing which is of no use.” - Miyamoto Musashi.

  10. #10
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,167
    Yes, it's a bug that MSVC highlights the wrong macro block. I don't know/think this happens if MSVC10, though.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  11. #11
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    OIC. And here I thought there's something wrong with the code. Thanks.
    ERROR: Brain not found. Please insert a new brain!

    “Do nothing which is of no use.” - Miyamoto Musashi.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. StretchDIBits() - weird behaviour..
    By lobo in forum Windows Programming
    Replies: 13
    Last Post: 10-04-2010, 11:23 PM
  2. weird behaviour with abs()
    By crazyinlove in forum C Programming
    Replies: 19
    Last Post: 02-27-2010, 11:58 PM
  3. Errors including <windows.h>
    By jw232 in forum Windows Programming
    Replies: 4
    Last Post: 07-29-2008, 01:29 PM
  4. Quantum Random Bit Generator
    By shawnt in forum C++ Programming
    Replies: 62
    Last Post: 06-18-2008, 10:17 AM
  5. Replies: 16
    Last Post: 04-20-2008, 01:15 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21