Search code examples
c++windowsdllexport

dllexport pure virtual class with private implementation not working?


I have a library which I'm porting to Windows/MSVC. The library is C++, and uses the following pattern to hide the implementation. I'm trying to use the suggested way to export the entire class with dllexport on the class declaration.

#define API __declspec(dllexport)

class API Something
{
public:
    static Something * instantiate(); 

    void doSomething() = 0;
    // etc
};

Then there is a private implementation which implements the static factory method and all the other methods.

// SomethingImpl.h

class SomethingImpl : public Something
{
    //... normal overrides
}

// SomethingImpl.cpp

Something * SomethingImpl::instantiate()
{
    return new SomethingImpl();
}

void SomethingImpl::doSomething()
{
    // something great
}

However when I think link the DLL to my application, all these symbols are not found by the linker (LNK2019). I suppose that because they are pure virtual methods it assumes they are not needed? Any hints?

The other more normal classes are linking OK, and when I see the DLL in dependency walker, the symbols are definitely not there for these classes.

Thanks


Solution

  • Your assumption is correct in the sense, that the base class (Something) is not exported. More specifically, there is no actual code generated for the base class (since it is a pure virtual class). Hence there are no symbols that could be exported.

    On the derived class (SomethingImpl) however you have to dllexport the private implementation for the consumer of the dll. The dllexport of the base class is not inherited by the derived class. But you have to export these symbols in order of allowing a consumer actually using this code. That does not mean your implementation details become "public" to the consumer.

    As an example, imagine a consumer of your dll declares a class with a member of type Something. When this class calls Something::instantiate(), the linker needs to know which actual address needs to be called. Hence your implementation must be exported.