unresolved external symbol for __declspec(dllimport) when using dll to export class

Chtoucas picture Chtoucas · Mar 17, 2012 · Viewed 44k times · Source

I want to define a derived class based on a dll exported class. The base class is defined in Project A, and the derived class is in Project B.

Firstly, in Project A, preprocessor MYDLL_BUILD is defined. And I use a header file to specify export/import:

    #if !defined(MYDLL_BUILD)
    #   pragma comment(lib, "myDll.lib")
    #endif

    #if defined(MYDLL_BUILD)
    #   define MYDLL_API __declspec(dllexport)
    #else
    #   define MYDLL_API __declspec(dllimport)
    #endif

Then I define the base class:

class MYDLL_API DllObject
{
public:
    virtual ~DllObject() {}
protected:
    DllObject() { m_count = 3; }
private:
    int m_count;
};

In Project B, the preprocessor MYDLL_BUILD is not defined. Here is the derived class:

class MyClass : public DllObject
{
public:
    ~MyClass(){}
    MyClass() { m_data = 20; }
private:
    int m_data;
}; 

I have included the dll and lib file, but still I get the unresolved external symbol error:

2>Test_Entry.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall ADAI::DllObject::~DllObject(void)" (__imp_??1DllObject@ADAI@@UAE@XZ) referenced in function "public: virtual __thiscall MyClass::~MyClass(void)" (??1MyClass@@UAE@XZ)
2>Test_Entry.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) protected: __thiscall ADAI::DllObject::DllObject(void)" (__imp_??0DllObject@ADAI@@IAE@XZ) referenced in function "public: __thiscall MyClass::MyClass(void)" (??0MyClass@@QAE@XZ)
2>c:\Users\Adai\Documents\Visual Studio 2010\Projects\Test_Main\Debug\Test_Main.exe : fatal error LNK1120: 2 unresolved externals

I searched online, most of the answers claim that the lib is missing. But those instructions do not solve my problem.

When I change

    class MYDLL_API DllObject

to

    class __declspec(dllexport) DllObject 

The solution compiles with no error. I really do not understand the reason. Can someone please help? Thanks in advance.

Answer

Tomek Szpakowicz picture Tomek Szpakowicz · Mar 19, 2012

The reason is inlining.

In short, to make inline functions possible C++ must allow the same definition of function to be included and compiled in multiple compilation units (basically .cpp files) without causing errors. Compiler can, but doesn't have to emit code for any of this definitions. Then linker is allowed to chose one copy.

This complicates dll creation because you need to export exactly one copy but compiler doesn't know which copy is the right one. In this case by adding some code to DllObject.cpp you made the compiler emit code for DllObject and linker had some copy of DllObject::~DllObject to export.

I cannot give you more detailed explanation of your particular case because I don't know full source and compilation options for your project.