Search code examples
c++classdlldllexport

What is the best way to construct a class object in a C++ DLL in a way that it is accessible from within any exported function of DLL?


If we have a C++ DLL with 4 exported functions, what is the best way to construct an object of a class when the DLL is loaded (by LoadLibrary), in a way that we can access public methods of that class from within any exported function (exported by extern "C" __declspec(dllexport)). I remember global stuff is evil.

Looking for a better way of doing the following (the following is not the best approach):

namespace namespace_top_of_CMS_DLL{
    CMS CMS_Object      =CMS();
    CMS*CMS_Ptr_Object  =&CMS_Object;   
}

extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runFullStructure(){
    namespace_top_of_CMS_DLL::CMS_Ptr_Object->runFullStructure();
}

extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runSubStructures(){
    namespace_top_of_CMS_DLL::CMS_Ptr_Object->runSubStructures();
}

extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runReducedStructure(){
    namespace_top_of_CMS_DLL::CMS_Ptr_Object->runReducedStructure();
}

Solution

  • "Looking for a better way of doing the following (the following is not the best approach): ..."

    I'd prefer to put the global class instances into an unnamed namespace in the translation unit where your exported functions are implemented.

    Remove the declarations for CMS CMS_Object and CMS*CMS_Ptr_Object from the header file. Also have a separate translation unit for the implementation, and move the inline definitions of your exxported functions there

    Header:

    extern "C" __declspec(dllexport)
    void OPS_CMS_DLL_runFullStructure();
    
    extern "C" __declspec(dllexport)
    void OPS_CMS_DLL_runSubStructures();
    
    extern "C" __declspec(dllexport)
    void OPS_CMS_DLL_runReducedStructure();
    

    Implementation

    namespace { // << note no namespace here
        CMS CMS_Object      =CMS();
        CMS*CMS_Ptr_Object  =&CMS_Object;   
    }
    
    void OPS_CMS_DLL_runFullStructure(){
        CMS_Ptr_Object->runFullStructure();
    }
    
    void OPS_CMS_DLL_runSubStructures(){
        CMS_Ptr_Object->runSubStructures();
    }
    
    void OPS_CMS_DLL_runReducedStructure(){
        CMS_Ptr_Object->runReducedStructure();
    }
    

    That way you can ensure, they can be accessed from your exported function implementations exclusively.

    "I remember global stuff are evil."

    It's true that global variables are an indication for bad design in most cases. These are prone to clutter code, and being unintentionally used from other code, which is out of your control.
    Having module private globals is perfectly OK.