Let's walk through the code. This is just preprocessing done to prepare the file for different compilers. What it is achieving to do is to emulate the __attribute__((constructor)) attribute from gcc on multiple different compilers, and in standard C++ as well. The first part of the code:
1 2 3 4 5
|
#ifdef __cplusplus // Default
#define INITIALIZER(f) \
static void f(void); \
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
static void f(void)
| |
__cplusplus will be defined if the translation unit is being compiled by a C++ compiler (as opposed to a C compiler). This makes sure of this before the file is actually compiled
Next, a macro INITIALIZER() is defined. Its single parameter, f, is used to declare a structure and it is concatenated into the name of that structure using the ## preprocessing operator. For example, if it is called like this:
INITILIZER(hello) { /*...*/ }
The macro expands to this:
1 2 3
|
static void hello(void);
struct hello_t_ { hello_t_(void) { hello(); } }; static hello_t_ hello_;
static void hello(void) {/*...*/}
| |
So this basically declares a structure called hello_t_ and creates a static object. Since static objects are initialized before main()'s code begins running, it causes a constructor call to hello_t_, which in turn calls the hello() function that you are defining. This makes it so that code can run immediately before the start of main(), like a constructor call.
1 2 3 4 5 6 7 8 9 10 11
|
#elif defined(_MSC_VER) // MSVS
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64 // MinGW
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
| |
These all do the same thing as the first one, but they use compiler specific methods rather than the standard C++ method using compiler specific attributes. The stack overflow link explains the MSVC case:
For MSVC, this places a pointer to the function in the user initializer section (.CRT$XCU), basically the same thing the compiler does for the constructor calls for static C++ objects. For GCC, uses a constructor attribute. |
The last one is for GCC and Clang:
1 2 3 4 5
|
#elif // GCC, Clang
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
| |
It uses the __attribute((constructor)) attribute from gcc/clang to mark a function as an initializer function and does the same thing.