Writing a DLL containing C++ classes

Putting functions into a DLL is a good thing. It helps you to reuse stuff, save space on updates, save build time etc. To write a DLL the proper way you have to keep some things in mind though. Those hints are basically the “best-practice” from this page.

A DLL is a library, a collection of data and/or code. To use a DLL, on Windows (on Unixes this is a bit different) you need a .h file(s) declaring the functions and classes contained in the DLL (if any),  a .lib file containing stubs for the functions in the DLL, possibly a .def file containing the exported functions and the actual .dll file containing the code and data.

When writing a DLL you will want to export some functions from the DLL you want make available to the outside. Those you need to declare with:

class __declspec(dllexport) CC {
    void foo();
};

Now the problem with that is that the compiler does name mangling – it gives the functions/classes a unique name – but how it does this depends on the compiler and its version. A DLL compiled by one compiler can thus not be used with a different compiler. UNLESS you define the functions as extern “C” and their call type as APIENTRY. The problem with that again is, that those are C functions. APIENTRY is also usually __stdcall, meaning those can’t be (non-static) class members – Not what you want unless you have “all static” classes.
The workaround is using a virtual base class for your class and providing an object creation/destruction function:

class CCInterface { // notice: no __declspec(dllexport) here
    virtual void foo() = 0;
    virtual void Release() = 0;
};

class CC { // notice: no __declspec(dllexport) here either
    void foo() { // do something };
    void Release() {delete this;};
};

extern "C" CCInterface * APIENTRY createCC() {
    return new CC;
}

This is also more or less the way COM works, which is in turn why all compilers support this. The downside is that you can not put the creation function into the interface and you need to explicitly call the release function. You could get around the Release call by using an auto_ptr or use the AutoClosePtr from the original document.

When you create a class that is a singleton you can get around having to call Release() by destroying the object when the DLL is detached from the last process:

static int attached = 0;
static CC * instance = nullptr;

extern "C" CCInterface * APIENTRY getCCInstance() {
    if (nullptr == instance) {
        instance = new CC;
    }
    return instance;
};

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    // Perform actions based on the reason for calling
    switch(fdwReason) {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
            attached++;
            break;
        case DLL_PROCESS_DETACH:
        case DLL_THREAD_DETACH:
            // Delete instance when the last process/thread detaches
            if (0 >= --attached && nullptr != instance) {
                delete instance;
                instance = nullptr;
            }
            break;
    }
    return TRUE; // Successful DLL_PROCESS_ATTACH
}

You could also use an auto_ptr for that purpose.

Published by HorstBaerbel

Software developer by trade and interest, but I venture into the electronics- and diy-world from time to time.

One thought on “Writing a DLL containing C++ classes

  1. I have reviewed the original post before coming across this and could say, this was a short and precise revision of what the original author had intended to explain about \”Mature\” way of exporting(without exposing) C++ classes and public member functions. Also just to clarify still there might be possibility for memory leaks as the cleanup of pointer should occur in a destructor since the in the event of exception the stack unwinding starts with the destructor wheras in the mean time if the DLL is still loaded and is being used by other threads in a multi programming environment, it might lead to memory leak before DLL_DETACH_PROCESS is being called for detaching the DLL.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website at WordPress.com
Get started
%d bloggers like this: