Consider the pair of functions below:
double MYAPI foo(double x) {
return x;
}
Register register_foo_([] {
return reg(&foo, "foo", ...); // function name repeated used
});
register_foo_
is a global variable, initialized before dllmain
, whose constructor takes a lambda that repeatedly references the name of the function above it literally. It would be great if the registration code can move inside the function above to reduce the chance of making an error. I tried:
double MYAPI foo(double x) {
static Register register_foo_([] {
return reg(&foo, "foo", ...); // static local does not initialize before dllmain
});
return x;
}
If the above code works, then I can easily turn it into a macro that makes use of __FUNCNAME__
. Is there a way to force the initialization of static local variable register_foo_
before dllmain?
Global (namespace) variables or static class members 1 live for the entire execution of the program: they must be initialized before main() is run and destroyed after execution finishes.
For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator (::), then the variable name. Now we can assign some value.
It is mandatory to initialize the static variable using the static keyword in C else it will return an error. The static variable is only initialized the first time when a function is called. In a static variable, the memory of a static variable is allocated.
The only way to initialize static final variables other than the declaration statement is Static block. A static block is a block of code with a static keyword. In general, these are used to initialize the static members. JVM executes static blocks before the main method at the time of class loading.
Static variables local to a function (method) are initialized on first use of the function they're in. (They're zero-initialized at program load, then initialized "properly" via code when the function is first entered.) See the answers to this question. So your proposed movement of that code into the function changes the semantics of initialization, and it won't work.
Your original code worked, so what you apparently wanted was to move the code inside the function so it was somehow tied closer together in your mind - or the mind of a reader of the code - so that you could see that your string constant name and function name were right. Also maybe so that you could ensure the registration was done. And therefore what you want is to accomplish DRY.
The traditional (and only) way to accomplish that is by using a preprocessor macro that expands into the registration call and the function header.
You proposed using a macro yourself - now expand the macro so it not only generates the registration function but also the function header.
I suppose you want to achieve a syntax similar to:
DEFINE_FUNC(void, foo, (double x)) {
return x;
}
... and have the boilerplate autogenerated. That's actually very simple to do if you bring the Register
above the function, with the help of a declaration:
#define DEFINE_FUNC(Ret, name, args) \
Ret name args; \
Register register_##name##_([] { \
return reg(&name, #name, ...); \
}); \
Ret name args
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With