首页 > 解决方案 > 使用 lambda 的 DLL 中未解析的外部符号

问题描述

我有一个 DLL 的以下结构部分:

实用程序.h

#ifdef _EXPORTS
#    define UTILS_API __declspec(dllexport)
#else
#    define UTILS_API __declspec(dllimport)
#endif

namespace Utils
{
    static auto MyCustomComparator = [](std::shared_ptr<IMyType>& o1, std::shared_ptr<IMyType>& o2) {
        // do some stuff and compare o1 and o2
    };

    using MyCustomPriorityQueue = std::priority_queue<std::shared_ptr<IMyType>, std::vector<std::shared_ptr<IMyType>>, decltype(MyCustomComparator)>;

    UTILS_API void Foo(MyCustomPriorityQueue& myQueue);
}

实用程序.cpp

#include "Utils.h"

namespace Utils
{
    UTILS_API void Foo(MyCustomPriorityQueue & myQueue)
    {
        // implementation
    }
}

这些被构建到一个 DLL 中,然后链接到一个可执行文件中,该可执行文件创建MyCustomPriorityQueue并调用Foo.

工具.cpp

#include "Utils.h"

int main()
{
    MyCustomPriorityQueue myQueue(MyCustomComparator);

    // add things to queue
    myQueue.emplace(...)

    Utils::Foo(myQueue);
}

这无法unresolved externalsFooAPI 上构建。关于可能导致这种情况的任何想法?我知道,直到我添加了带有自定义比较器的优先级队列作为导出 API 的一部分(它曾经是内部的Foo),这一切都起作用了,所以在链接和确定自定义优先级队列的类型期间肯定会出错也许?

error LNK2001: unresolved external symbol "__declspec(dllimport) void __cdecl Utils::Foo(struct class std::priority_queue<class std::shared_ptr<class Utils::IMyType>,class std::vector<class std::shared_ptr<class Utils::IMyType>,class std::allocator<class std::shared_ptr<class Utils::IMyType> > >,class <lambda_19161500ece6d0a8a5b52705767e713b> const > &)" (__imp_?Foo@Utils@@$priority_queue@V?$shared_ptr@VIMyType@Utils@@@std@@V?$vector@V?$shared_ptr@VIMyType@Utils@@@std@@V?$allocator@V?$shared_ptr@VIMyType@Utils@@@std@@@2@@2@$$CBV<lambda_19161500ece6d0a8a5b52705767e713b>@@@std@@@Z)
bin\Tool.exe : fatal error LNK1120: 1 unresolved externals

标签: c++c++11dll

解决方案


您必须确保这一点:通过创建 DLL,应该定义宏 _EXPORTS。在使用 DLL 的客户端代码中,不应定义宏 _EXPORTS。

还要注意关于lambda:包含相同头文件的 2 个编译单元将看到不同的 lambda 类型,因为每个 lambda 都有不同的类型。例如,在此示例代码中:

auto a = []() {};
auto b = []() {};

a 和 b 类型会有所不同。

我认为您不能在您的情况下使用 lambda。只需声明常规类型。

根据您编译的平台,您可以使用dumpbin(如果是 win)或readelf(如果是 unix)来检查 dll 的导出符号和客户端的导入符号。


推荐阅读