tags:

views:

196

answers:

3

So the common (at least VS 2005 states) way to define exports/imports for a DLL is:

#ifdef MY_EXPORTS
#define MY_API __declspec(dllexport)
#else
#define MY_API __declspec(dllimport)
#endif

class MY_API MyClass {
    ...
};

This works great if I'm just building my code as a DLL. However, I want to have the option of using a static library OR a DLL. Now one obvious (but terrible) solution, is to copy all the code, removing the DLL 'MY_API' defines. Now what would seem a much better approach is a command line switch to either define, or not define the DLL stuff. However in the case of a static library what should 'MY_API' be?

#ifdef DLL_CONFIG
    #ifdef MY_EXPORTS
    #define MY_API __declspec(dllexport)
    #else
    #define MY_API __declspec(dllimport)
    #endif
#else
    #define MY_API // What goes here?
#endif

class MY_API MyClass {
    ...
};

Now assuming that this can be done will there be issues when a user of the library includes the header files (ie. will they have to define 'DLL_CONFIG')?

+5  A: 

Nothing.

Leave it as #define MY_API and all instances of MY_API will simply vanish.

You can add new build configurations, such as Debug - DLL and Release - DLL that mimic the others except they #define DLL_CONFIG.

To clone a configuration, get to the configuration manager (like the drop down of the Debug/Release list box), then under 'Active solution configuration' select new. You can now name it "Debug - DLL" and set Copy Settings to Debug and now that's left to do is define DLL_CONFIG.

To do this, go to project properties->configuration properties->C/C++->Preprocessor, and type DLL_CONFIG in there. You will also see that's where things like NDEBUG and WIN32 are defined.

Like haffax said, use project specific names. I would recommend something like:

#ifdef THEPROJECT_USE_DLL
    #ifdef THEPROJECT_BUILDING_PROJECT
        #define THEPROJECT_API __declspec(dllexport)
    #else
        #define THEPROJECT_API __declspec(dllimport)
    #endif
#else
    #define THEPROJECT_API
#endif

Now users of your DLL just #define THEPROJECT_USE_DLL if they are using the DLL version, just like your "- DLL" configurations have.

GMan
+1  A: 

Just define MY_API as empty. Like this:

#ifdef DLL_CONFIG
    #ifdef MY_EXPORTS
    #define MY_API __declspec(dllexport)
    #else
    #define MY_API __declspec(dllimport)
    #endif
#else
    #define MY_API
#endif

In case of static linking no declspec is necessary.

Users of your library will have to define DLL_CONFIG if they want to use it as a dll or not define it if they want to use it as a static library. There won't be any issues as is. This kind of configuration is done in many libraries.

Edit: Of course you shouldn't use the names MY_EXPORTS and DLL_CONFIG as such. Use project specific prefixes for all of your macros, so that there are no name clashes.

haffax
A: 

Do nothing. No special calling convention is needed to link against a static library. The only thing you need to do, is to make sure that the linker links with your.lib.

Magnus Skog