DLL Main on Windows Vs. __attribute__((constructor)) entry points on Linux

后端 未结 2 1224
旧巷少年郎
旧巷少年郎 2021-02-09 21:45

Consider code

EXE:

int main ()
{

    printf(\"Executable Main, loading library\\n\");
#ifdef HAVE_WINDOWS
    HMODULE lib = LoadLibrary         


        
2条回答
  •  情深已故
    2021-02-09 22:08

    There is a way:

    StartupCleanup.cpp:

    // Redefine the same StartupCleanup class as it is in DllMain.cpp
    // Definition of constructor and destructor must stay in DllMain.cpp
    // And including here any headers which may define normal static or global constructors/destructors is strictly forbidden!
    struct StartupAndCleanup
    {
        /**/  StartupAndCleanup();
        /**/ ~StartupAndCleanup();
    };
    
    // It ensures this instance is the first to be constructed *BEFORE* any normal static or global constructors calls
    // and the last to be destructed *AFTER* all normal destructors calls.
    // The key to do so is using #pragma init_seg(lib), but that key applies for all the static and global constructors/destructors in the same .obj file! 
    #pragma warning(push)
    #pragma warning(disable:4073)
    #pragma init_seg(lib)
    #pragma warning(pop)
    
    // this function is just to keep linker from discarding startupAndCleanup.obj when linking to an executable or dll
    void needStartupAndCleanup()
    {
    }
    
    static StartupAndCleanup startupAndCleanup;
    

    DllMain.cpp:

    ...
    // Definition of this class should be the same as in StartupAndCleanup.cpp!
    struct StartupAndCleanup
    {
        /**/  StartupAndCleanup();
        /**/ ~StartupAndCleanup();
    };
    
    StartupAndCleanup::StartupAndCleanup()
    {
        // Do your initialization here !
    }
    
    StartupAndCleanup::~StartupAndCleanup()
    {
        // Do your termination here !
    }
    

    You DllMain must be just an empty shell and do your usual safe initialization and termination in those constructor and destructor like for Linux.

    NOTE: Beware! you cannot create/delete threads inside static or global constructors/destructors if you plan to synchronize them. That's all folks !

    EDIT: you also need to call needStartupAndCleanup() in a function you know it is linked, otherwise the object file StartupCleanup.obj will be discarded and those global constructor/destructor as well.

提交回复
热议问题