使用dll导出类时__declspec(dllimport)的未解析外部符号

Cht*_*cas 16 c++ inline dllimport dllexport visual-c++

我想基于dll导出的类定义派生类.基类在项目A中定义,派生类在项目B中定义.

首先,在项目A中,定义了预处理器MYDLL_BUILD.我使用头文件来指定导出/导入:

    #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
Run Code Online (Sandbox Code Playgroud)

然后我定义基类:

class MYDLL_API DllObject
{
public:
    virtual ~DllObject() {}
protected:
    DllObject() { m_count = 3; }
private:
    int m_count;
};
Run Code Online (Sandbox Code Playgroud)

在项目B中,未定义预处理器MYDLL_BUILD.这是派生类:

class MyClass : public DllObject
{
public:
    ~MyClass(){}
    MyClass() { m_data = 20; }
private:
    int m_data;
}; 
Run Code Online (Sandbox Code Playgroud)

我已经包含了dll和lib文件,但仍然得到了未解析的外部符号错误:

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
Run Code Online (Sandbox Code Playgroud)

我在网上搜索,大多数答案声称lib缺失.但这些说明并没有解决我的问题.

当我改变

    class MYDLL_API DllObject
Run Code Online (Sandbox Code Playgroud)

    class __declspec(dllexport) DllObject 
Run Code Online (Sandbox Code Playgroud)

解决方案编译时没有错误.我真的不明白原因.有人可以帮忙吗?提前致谢.

Tom*_*icz 6

原因是内联.

简而言之,为了使内联函数成为可能,C++必须允许在多个编译单元(基本上是.cpp文件)中包含和编译相同的函数定义,而不会导致错误.编译器可以,但不必为任何此定义发出代码.然后允许链接器选择一个副本.

这会使dll创建变得复杂,因为您只需要导出一个副本,但编译器不知道哪个副本是正确的.在这种情况下,通过向DllObject.cpp添加一些代码,您使编译器为其发出代码,DllObject并且链接器具有一些DllObject::~DllObject要导出的副本.

我不能给你更详细的解释你的具体案例,因为我不知道你的项目的完整源代码和编译选项.

  • 因此在.cpp模块中包含.h不足以创建它?您认为DLL生成至少可以将此标记为错误... (3认同)