如何修复 C++ DLL 中未解析的外部符号错误?

How do I fix an Unresolved External Symbol error in my C++ DLL?

提问人:Miguel P 提问时间:11/2/2012 最后编辑:KariMiguel P 更新时间:3/3/2019 访问量:9853

问:

我有一个dll,它可以访问其项目之外的一些类(我使用的是Visual Studio,所以我有两个项目)。问题是,在dll包含的标头中,在dll项目之外,只有函数体,如下所示:

x.h

class x
{
    void myFunc();
}

在另一个 cpp 文件中,在 dll 文件之外:

#include "x.h"

x::myFunc()
{
    //.....
}

dll 只获取函数的主体,所以当我编译时,我得到很多未解析的外部符号(我很确定这就是问题所在,因为我在另一个项目中使用另一个完全内置在 .h 文件中的类进行了测试,并且没有错误)。那么我该如何解开这个谜团呢?

C++ 函数 DLL 范围 未解析 - 外部

评论


答:

1赞 WeirdlyCheezy 11/2/2012 #1

导入标头只有函数签名是正常的;实际的函数体已经编译到 DLL 二进制文件中,并在链接时通过链接到实际 DLL 进行解析。

首先要尝试的是确保您确实链接到所述 DLL。仅仅包含标头是不够的,您还需要链接到二进制文件。因此,在项目配置中,需要添加一个链接,指向(例如)在编译 DLL 时(如果在 MSVC 中)与 DLL 一起创建的 .lib 文件。此 lib 文件让链接器知道如何将通过导入标头包含的函数签名连接到 DLL 中包含的实际实现。如果您在不同的平台上,机制可能会略有不同,但概念会相似。

编辑: 下一步是确保二进制文件实际上正在导出您尝试链接的符号。确保所有接口签名都通过 __declspec(dll_export) 前缀导出。通常,这被包装在 IFDEF 中,以便在编译 DLL 时声明标头导出,但在该标头包含在客户端项目中时不声明导出。接下来,您可以使用 dumpbin 检查损坏的导出名称,看看是否有任何意外。

这是您的示例的修改版本,它说明了这种导出方式(注意,我还没有测试过这是否编译,对于任何拼写错误,我们深表歉意):

#ifdef BUILDING_MYDLL
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif

class MYDLL_API x
{
    void myFunc();
}

然后,将配置设置为在编译 dll 时定义 BUILDING_MYDLL,但在编译可执行文件时不定义。这样,函数仅在编译库 dll 时标记为导出。现在,您可以使用MYDLL_API标记公共 API 函数,并且它们应该在构建期间导出。

请注意,dll_export、dll_import 和 declspec 都是非常特定于 MSVC 的构造。其他编译器/运行时以不同的方式处理符号导出。

评论

0赞 Miguel P 11/2/2012
如果你说我需要将我的主项目(例如应用程序)链接到dll,我已经这样做了,还是我错了?
0赞 Miguel P 11/2/2012
在我的主项目配置中。在链接器输入中,我在“其他依赖项”中添加了 lib 文件。
0赞 WeirdlyCheezy 11/2/2012
好的,很高兴知道。如果它找到了那个库,那么下一步就是找出为什么会出现符号不匹配。您是否正在通过 dll 导出导出 DLL 标头中的签名?
0赞 Miguel P 11/2/2012
我应该在dll中使用__declspec(dll_export)还是在我尝试包含的标头中使用?不好意思。。。
0赞 WeirdlyCheezy 11/2/2012
编译 DLL 时,您可以在 x.h 中 x::myFunc() 前面使用它。我将添加一些示例源。
1赞 Mike Trusov 11/2/2012 #2

有多种方法可以将 DLL 链接到 Windows 上的应用,请查看以下现有问题/答案:https://stackoverflow.com/a/2060508/1701823