使用 lambda 的 DLL 中未解析的外部符号

Unresolved External Symbols in DLL using lambda

我有以下 DLL 结构部分:

Utils.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);
}

Utils.cpp

#include "Utils.h"

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

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

Tool.cpp

#include "Utils.h"

int main()
{
    MyCustomPriorityQueue myQueue(MyCustomComparator);

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

    Utils::Foo(myQueue);
}

这无法在 Foo API 上使用 unresolved externals 构建。关于什么可能导致这种情况的任何想法?我知道,直到我添加带有自定义比较器的优先级队列作为导出的 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

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

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

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

类型 a 和 b 会有所不同。

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

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