动态库连接时的初始化函数

Linux

Linux上使用GCC构建动态链接库时,可以使用__attribute__((constructor))__attribute__((destructor)) 函数属性来输出DLL的构造和析构函数。构造函数会在dlopen返回前或库被装载时调用,析构函数会在 dlclose返回前或者main函数返回后,或者卸载库过程中被调用。

对于加载Haskell代码编写的动态链接库,使用示例如下:

__attribute__((constructor)) static void hslib_init() {
    static int argc = 1;
    static char *argv[] = {"HsLib.so", NULL};
    hs_init(&argc, &argv);
}

__attribute__((destructor)) static void hslib_final() {
    hs_exit();
}

此外,在Linux系统中,还可以通过.init.fini机制来完成动态链接库的初始化和退出处理,在 使用ld构建动态链接库时,通过-init -fini 参数指定构造和 析构函数。如果直接使用gcc完成链接工作,相应的命令行参数为-Wl,-init, 和-Wl,-fini,。但是,这种方式已经呗标为OBSOLETE/DANGEROUS2。某些环境下, 进程可能会非常依赖GCC自动添加的.init函数和.fini函数,因此这种方式可能会导致一些无法预测 和复现的运行现象,甚至导致进程崩溃。

Windows

Windows系统上,使用LoadLibraryFreeLibrary函数来加载和卸载动态链接库,都会调用DllMain函数。这个函数的原型为3:

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);

其中,reason参数指明了调用DllMain函数的原因,可选值包括:

  • DLL_PROCESS_ATTACH:第一次加载DLL、将DLL文档映射到进程的地址空间时。
  • DLL_PROCESS_DETACH:当调用FreeLibrary函数,DLL被从进程的地址空间解除映射时,通过DLL进行清理 工作。
  • DLL_THREAD_ATTACH:当进程创建一个新的线程时系统会查看当前映射到进程地址空间的所有DLL文档映像、 并调用DllMain函数。
  • DLL_THREAD_DETACH:当线程函数返回时系统会自动调用ExitThread函数,系统会查看当前映射到进程 地址空间的所有DLL文档映像、并调用DllMain函数,通知DLL进行线程级的清理工作。

对于加载Haskell代码编写的动态链接库,DllMain函数如下例:

BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    static int argc = 1;
    static char *argv[] = {"HsLib.dll", NULL};
    switch (fdwReason) {
        case DLL_PROCESS_ATTACH:
            hs_init(&argc, &argv);
            break;
        case DLL_PROCESS_DETACH:
            hs_exit();
            break;
    }
    return 0;
}

你可能感兴趣的:(Linux,C++,编译,c++)