The Linux Page

Why aren't my C++ class public functions exported with __dllexport?

I had a problem for the last 2 days and had a hard time to determine what it was...

Now I know how to resolve such a problem, so I wanted to share my finding! It's very simple, but writing about it here may help me later to save time...

So... I wrote a C++ class for a DLL, this means I want it's public functions to be exported:

class MY_CLASS_API myClass {
public:
    ... // declarations and functions
};

Up to here, nothing strange.

The MY_CLASS_API is a macro defined in some random header file:

#if defined(MSWINDOWS)
#  if MY_CLASS_EXPORTS
#    define MY_CLASS_API __declspec(dllexport)
#  else
#    define MY_CLASS_API __declspec(dllimport)
#  endif
#else
// no MS-Windows, ignore
#  define MY_CLASS_API
#endif

Up to here, nothing strange...

That would work great by itself, but I needed a special case to build a tool. The fact is that the DLL required a preprocessor building a file that is added to its resources. That tool uses the same code as the DLL to load some XML files. Using the same code gives me the advantage to have a free test (a test that I did not write on purpose to test one of the DLL classes.)

This tool requires the class in question (the one that wouldn't link properly) to use the non-MS-Windows MY_CLASS_API (the last one with nothing in it.)

For this purpose I added a condition in the first #if to skip the first part whenever the tool is being created:

#if defined(MSWINDOWS) && !defined(PREPROCESSOR_TOOL_NAME)

Because of the many changes I made, the condition remained false when it should have been true (i.e. a name was misspelled.) I had no clue, obviously, since I did fix the name, albeit improperly, it looked correct to me. (I wrote, I know!)

So... the hours searching gave me no answer other than everything works great on my end... no reason for the missing class from the DLL. Until I had the idea to add an #error statement:

#if defined(MSWINDOWS) && !defined(PREPROCESSOR_TOOL_NAME)
#  if MY_CLASS_EXPORTS
#error "Getting the dllexport!"
#    define MY_CLASS_API __declspec(dllexport)
#  else
#    define MY_CLASS_API __declspec(dllimport)
#  endif
#else
// no MS-Windows, ignore
#  define MY_CLASS_API
#endif

That #error must generate an error if the file in question is compiled with the wrong flags. When I first tested, I tried to compile the entire DLL and seen all those errors. Great, I thought. It works as expected, the dllexport API is used. Perfect.

The truth is that it was working with all the other files...

What I really had to do is compile just and only the file that was causing the problem!!!

Once I tried to compile myClass by itself it... worked! Which means the #error was not executed and therefore one of the first or second #if was wrong.

At that point I noticed that the .cpp file misspelled the  PREPROCESSOR_TOOL_NAME flag. Fixing that flag fixed everything and now it again works like a charm.