Abh*_*ain 5 c++ linux windows shared-libraries dllmain
考虑代码
可执行程序:
int main ()
{
printf("Executable Main, loading library\n");
#ifdef HAVE_WINDOWS
HMODULE lib = LoadLibraryA ("testdll.dll");
#elif defined(HAVE_LINUX)
void * lib = dlopen("testdll.so", RTLD_LAZY);
#endif
if (lib) {
printf("Executable Main, Freeing library\n");
#ifdef HAVE_WINDOWS
FreeLibrary (lib);
#elif defined(HAVE_LINUX)
dlclose(lib);
#endif
}
printf("Executable Main, exiting\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
DLL
struct Moo
{
Moo() { printf("DLL Moo, constructor\n"); }
~Moo() { printf("DLL Moo, destructor\n"); }
};
Moo m;
#ifdef HAVE_WINDOWS
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
printf("DllMain, DLL_PROCESS_ATTACH\n");
break;
case DLL_THREAD_ATTACH:
printf("DllMain, DLL_THREAD_ATTACH\n");
break;
case DLL_THREAD_DETACH:
printf("DllMain, DLL_THREAD_DETACH\n");
break;
case DLL_PROCESS_DETACH:
printf("DllMain, DLL_PROCESS_DETACH\n");
break;
default:
printf("DllMain, ????\n");
break;
}
return TRUE;
}
#else
CP_BEGIN_EXTERN_C
__attribute__((constructor))
/**
* initializer of the dylib.
*/
static void Initializer(int argc, char** argv, char** envp)
{
printf("DllInitializer\n");
}
__attribute__((destructor))
/**
* It is called when dylib is being unloaded.
*
*/
static void Finalizer()
{
printf("DllFinalizer\n");
}
CP_END_EXTERN_C
#endif
Run Code Online (Sandbox Code Playgroud)
输出不同:
在窗户上
Executable Main, loading library
DLL Moo, constructor
DllMain, DLL_PROCESS_ATTACH
Executable Main, Freeing library
DllMain, DLL_PROCESS_DETACH
DLL Moo, destructor
Executable Main, exiting
Run Code Online (Sandbox Code Playgroud)
Linux的
Executable Main, loading library
DllInitializer
DLL Moo, constructor
Executable Main, Freeing library
DllFinalizer
DLL Moo, destructor
Executable Main, exiting
Run Code Online (Sandbox Code Playgroud)
在Windows上,Moo构造函数在DLLMain之前调用,而在linux上,在使用attribute((constructor))定义的Initializer之后调用.
为什么?
之前 没有调用Moo构造函数DllMain,它是从中 调用的DllMain.确切地说,它是从真实DllMain调用的,Windows首先调用的函数.这真正DllMain调用C++构造函数,然后调用您的C++ DllMain.这个真实的原因DllMain恰恰是初始化构造函数,这在C之前是不需要的
Linux(GCC/ELF)完全没有这个概念; 它只有构造函数.您的手动ctor和Moo的C++ ctor也是一样的.