c++dllheader-filesdllexportifndef

how in #ifdef identifier and #ifndef identifier declare identifiers


#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
// How to determine the identifier above?  
// Where did `MATHLIBRARY_API` came from?
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif

Another example:

#ifdef BUILD_DLL
    // same question here.where BUILD_DLL came from?
    #define DLL_EXPORT __declspec(dllexport)     
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif

I'm working on making a header file for a DLL, and I'm really stuck on this. I'm confused about what identifier I should use after #ifdef or #ifndef directives.


Solution

  • Asking where MATHLIBRARY_API comes from seems incongruous, as it's defined right there in the code.

    I suspect you're actually asking about using MATHLIBRARY_EXPORTS instead, since you later asked about BUILD_DLL (which is also a using case). So I'll base this answer on that.

    Definitions typically happen in one of two places:

    1. From #define earlier in the process. You can see that in operation in your code where it defines, for example, DLL_EXPORT.
    2. As a compiler flag such as -D MATHLIBRARY_EXPORTS.

    In terms of the actual names you can use, these are identifiers so have to follow certain rules set down in the standard(1).

    You are also responsible for managing "collisions" of those names between individual parts of the compilation process (such as your code and third-party code). So, if two header files that you use each had different definitions for TRUE, that could cause issues:

    #define TRUE 1
    #define TRUE (!0)
    

    As an example of using this (very similar to your MATHLIBRARY_EXPORTS/MATHLIBRARY_API example, I suspect), see the following code:

    #ifdef ACCESS_PRIVATE
        # define PRIVATE
    #else
        # define PRIVATE static
    #endif
    
    void public_function() { /* code goes here */ }
    PRIVATE void private_function() { /* code goes here */ }
    

    If you compile that with g++ -c -o file.o file.c, then private_function() will be static, so not visible outside of the current translation unit.

    However, if you added -D ACCESS_PRIVATE to the compiler flags, then the function would not be static and you would be able to access it from other code that you link.

    This sort of thing is often done for unit tests of otherwise private functions.


    (1) For allowable characters in identifiers, see the current iteration of the standard at time of this answer, C++20 5.10 Identifiers (or equivalent section in other iterations).

    This is functionally defined as having the first character drawn from the set (C allows for extra implementation-defined characters, C++ apparently does not):

    That character is then followed by zero or more subsequent characters which are either: