当使用dll导出类时,出现__declspec(dllimport)的未解决外部符号

17
我想基于一个导出类定义一个派生类。基类已在项目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

然后我定义基类:
class MYDLL_API DllObject
{
public:
    virtual ~DllObject() {}
protected:
    DllObject() { m_count = 3; }
private:
    int m_count;
};

在项目B中,预处理器MYDLL_BUILD未定义。这是派生类:
class MyClass : public DllObject
{
public:
    ~MyClass(){}
    MyClass() { m_data = 20; }
private:
    int m_data;
}; 

我已经包含了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

我在网上搜索,大多数答案声称缺少库。但这些说明并没有解决我的问题。
当我更改时......
    class MYDLL_API DllObject

to

    class __declspec(dllexport) DllObject 

这个解决方案编译没有错误。我真的不明白原因。有人可以帮忙吗?先谢谢了。

1
似乎 MYDLL_API 没有按照你的期望在项目 A 中被定义。让 VS 生成一个预处理版本的 DllObject 文件(右键单击文件,转到属性,展开 C/C++ 并查看预处理器选项)。确保输出包含 class __declspec(dllexport) DllObject 而不是 class __declspec(dllimport) DllObject - Praetorian
3
更新:我在DllObject.h中添加了一个函数,并在DllObject.cpp中实现它。除此之外,没有做任何更改,设置也是相同的。然后成功地编译了。 // DllObject.h MYDLL_API int foo(int n); class MYDLL_API DllObject { public: virtual ~DllObject() {} protected: DllObject() { m_count = 3; } private: int m_count; }; // DllObject.cpp int foo(int n) { return 0; } - Chtoucas
5
我面临完全相同的问题,打着键盘却不理解为什么会发生这种情况 :( - CygnusX1
2
@CygnusX1 我也是,基本上只有装饰上的细微差别。(尽管对我来说更像是拔头发而不是敲键盘) - user645280
1
我也是。在我的情况下,这是由于DLL使用UNICODE宏编译,但链接到它的可执行文件没有使用该宏。 - Mooing Duck
显示剩余4条评论
2个回答

7
原因是内联。
简而言之,为了使内联函数成为可能,C++必须允许在多个编译单元(基本上是.cpp文件)中包含和编译函数的相同定义而不会导致错误。编译器可以对其中任何一个定义生成代码,但不一定非得这样做。然后链接器可以选择一个副本。
这使得dll创建变得复杂,因为你需要精确地导出一个副本,但编译器不知道哪个副本是正确的。在这种情况下,通过向DllObject.cpp添加一些代码,你可以使编译器生成DllObject的代码,链接器有一份DllObject::~DllObject的副本可以导出。
由于我不知道你的项目的完整源代码和编译选项,所以无法给你提供更详细的解释。

3
在一个 .cpp 模块中包含 .h 文件不足以创建它?至少 DLL 生成应该将其标记为错误... - user645280

1
我今天遇到了同样的问题。我将来自我的版本的 DllObject.dll.lib文件包含进去,但没有起作用。
为了解决这个问题,我必须将.lib文件名添加到我的版本的项目的属性->链接器->输入->附加依赖项中。
如果这不起作用,您可能需要在属性->链接器->常规->附加库目录中添加.lib位置的目录地址。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接