2

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();
}
knoxgon
  • 1,070
  • 2
  • 15
  • 31
Megidd
  • 7,089
  • 6
  • 65
  • 142

3 Answers3

2

First of all, don't use absolute statements like "globals are evil". What is a global anyway? Even globals have some scope. If that scope makes logical sense, then it's certainly not evil. main is not evil, for example. An exported DLL function is similarly a "global". If you need to interact with that module, you're going to need some kind of way to access it.

You'll need to export at least 1 function from the DLL to use it, and use GetProcAddress. From there, you have any number of patterns to follow. The simplest is to just export C-style functions as you need them.

If you need C++ objects, DLLs can create a huge amount of headaches. I would recommend either exporting everything as C-style, or using COM.

Community
  • 1
  • 1
tenfour
  • 36,141
  • 15
  • 83
  • 142
1

"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.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
1

Be careful about exposing a class outside a dll. The C ABI is far simpler and far better defined than the complex C++ ABI. If templates are involved all guarantees go out the window.

So unless you want to commit to always using the same toolchain to compile your dll and exe, stick to your extern "C" __declspec(dllexport) method in your OP. For convenience you can always provide a C++ wrapper (header only).

doron
  • 27,972
  • 12
  • 65
  • 103