I have a dynamic library of c++ code that is cross platform and mostly just native c++. I then use this dynamic library from my main exe. Up until now all has been good on OSX using gcc. Now I'm on windows I am confused as to what method I should use to enter the dll. I don't have a DllMain function at present as this wasn't required in gcc (to my knowledge). My initial tests worked but on inspection revealed that strangely one of my class constructors was being called on dll load, so I figured I needed to do something more on windows. So do I:
- add a DllMain function?
- am I safe to just use the noentry compiler option?
When I do either of the above I start getting compiler complaints in the vein of ".CRT section exists there may be unhandled static initializers or terminators"
I have read up on this using this article, but any advice and clarity on the best way forward would be greatly appreciated. Its all a开发者_运维知识库 bit blurry in my head as to what I need to do.
Based on the .CRT error, you definitely need a DllMain function. For most Windows compilers, a DllMain will be provided for you automatically, so that you don't need to write one yourself. Based on other parts of your question it seems most likely that you are using Visual C++, whose CRT does provide a DllMain for you. So while you do need a DllMain, you don't need to write the code for it.
The default VC CRT DllMain is used to initialize the CRT for the DLL in question, and to initialise all the static/global variables that the dll provides.
The model for DLLs on Unix and Windows is significantly different, and you should think of each DLL as having a more 'private' set of state. Although, if all Dlls opt into the same version of the CRT dll, some of that state will then be shared.
Because the CRT is providing a DllMain for you, you should not throw /noentry on the linker.
The .CRT section exists error (which you must have seen by throwing /noentry) is telling you that you need a DllMain because you've got one or more objects in your DLL that require static initialisation.
Martyn
If it is just a library, then NOENTRY should suffice. DllMain is there to control events that happen with the DLL (i.e. attach, detach etc).
You can change the code (slightly) to avoid all entry points but main. Essentially, if you have any variable defined outside of the functions (globally but not statically linked), wrap them in a function call. Use the often-forgotten static function variables. Ie, change global declaration
SomeType var_name;
to this:
SomeType & var_name(){static SomeType var; return var;}
Similarly, you can change static class instance variables by changing this:
struct Container{
Container();
static Container instance;
};
Container Container::instance;
to this:
struct Container{
Container();
static Container & instance();
};
Container & Container::instance(){
static Container var;
return var;
}
This is essentially a singleton, but there might be some concurrency issues if the 1st time you access the instance will be from a multi-threaded environment. In fact, the thing to keep in mind is that unlike globally-defined variables, static locally-defined variables will be initialized the first time the function is called.
精彩评论