Use of "#define FOO" with no value assigned - other than as include guard?

99 views Asked by At

I'm trying to understand Steinberg's VST SDK.

What's the use of this:

#define PLUGIN_API 

without assiging any value in a header file and then PLUGIN_API occurring in many member functions' declarations/definitions for example like this:

Steinberg::tresult PLUGIN_API initialize (Steinberg::FUnknown* context) SMTG_OVERRIDE;
Steinberg::tresult PLUGIN_API terminate () SMTG_OVERRIDE;

Can someone explain this? The only use of #define without assigning a value that I know so far is using it as include guard.

Thank you in advance!

3

There are 3 answers

3
KamilCuk On BEST ANSWER

What's the use of this:

#define PLUGIN_API 

Of this particular line, none really. Basically to allow compilation of other parts of code, of functions declarations, where this macro is used. Without defining it to empty, other parts of code could error when compiling.

like this:

Steinberg::tresult PLUGIN_API initialize (Steinberg::FUnknown* context) SMTG_OVERRIDE;
Steinberg::tresult PLUGIN_API terminate () SMTG_OVERRIDE;

Sure, so PLUGIN_API expands to nothing and is useless. However, someone might later compile the code for windows into a dll. To make a symbol visible in dll, one would have to go through all function declarations and add the proper specifier to them:

 Steinberg::tresult __declspec(dllexport) initialize (Steinberg::FUnknown* context) SMTG_OVERRIDE;
 Steinberg::tresult __declspec(dllexport) terminate () SMTG_OVERRIDE;

Or with the define just do:

#if I_AM_COMPILING_ON_WINDOWS_FOR_A_DLL
#define PLUGIN_API __declspec(dllexport)
#else
#define PLUGIN_API /* nothing needed */
// defining PLUGIN_API to be empty, allows code to compile with no additional work
#endif
1
Acorn On

It can be used as annotations that other tools may use.

For instance, I've seen it used in code generators, binding generators, static analysis tools, automated documentation generators, reflection systems, serialization systems, etc.

It could also serve as plain documentation for the user, but that is rare.

0
Basile Starynkevitch On

It also enables your to code later in the same translation unit some conditional compilation with #ifdef PLUGIN_API ... #endif. For the human reader of such C++ code, it serves as a useful annotation.

For more explanations, see this C++ reference and Stroustrup's book: Programming in C++.

For an example of tool related to such preprocessing, see GNU autoconf with GNU automake

For an example of C++ software using similar tricks, see Qt & FLTK