Export like this:
class __declspec(dllexport) GUI
{...}
Import like this:
class __declspec(dllimport) GUI
{...}
Or simply define a macro like this:
#if _DEFINE_THIS_IN_YOUR_DLL_
#define CLASS_IMPORT_EXPORT __declspec(dllexport)
#else
#define CLASS_IMPORT_EXPORT __declspec(dllexport)
#endif
And directly use it:
class CLASS_IMPORT_EXPORT GUI
{
};
Be sure to have SINGLE header file for both DLL and its clients.
But it important to note that you sizeof
class in DLL and the client (EXE) must be same. It may happen, for example, that you have an array of SOME_SIZE which is defined as macro. In DLL, it might be 100
but in EXE it might be 200
(for whatsoever reason). This would just break the class, when you call some function the this
pointer would be correct; but not the class (that means sizeof(GUI-in-DLL) != sizeof(GUI-in-EXE)
.
Exporting a class also means exposing all of the data members included it it. This would mean exposing all other classes/structures/typedef/private variables and so on. For the solution, one might calculate the size of all data-members (say 154 bytes), and declare a char filler[154]
in class declration (for hiding actual data).
While this would practically work, compiler linker, debugger etc would not have any issues - but not flexible for programmer.
Irrespective if you hide the actual data declaration with filler-bytes or not, you must also ensure #pragma packing. For one, if DLL is having 4 bytes packing, and EXE is having (even by mistake) 1 byte packing, you are in total mess. And this mistake/bug is hard to detect!
The best solution, IMO, is to export a class having a pointer to class that implements the actual functionality. This means GUI_Internal
/GUI_Core
and exporting just GUI
having pointer of either of these classes:
class IMPORT_EXPORT GUI
{
GUI_Internal* pInternal; // 4/8 bytes only! EXACT
// ... Export functions
};
But this would require the client-of-DLL (at compiler level) to know what GUI_Internal
is. For this, just have a typedef
:
#if _DEFINE_THIS_IN_YOUR_DLL_
typedef GUI_Internal* ClassPointer;
#else
typedef void* ClassPointer
#endif
and use it:
class CLASS_IMPORT_EXPORT GUI
{
ClassPointer pointer; // Name is something else! ...
};
This obviously requires you to allocate pointer with instance of GUI_Internal, and forward functions to that class.