包装 C++ 共享库时在 C++/CLI 项目中出现链接错误

Linking error while in C++/CLI project while wrapping C++ shared library

我正在尝试将 C++ 库包装到托管项目可以使用它的状态。我使用的第三方库是共享库。它意味着 link 加载时间。我有头文件,.lib 文件是 DLL 导入库和 .DLL 文件。

这是我目前所做的:- 1.创建CLR项目。 2. 在 C/C++->General->Additional Include Directories 添加头文件路径 3. 在Linker->General中设置'Additional Library Directories'。 4. Linker->Input->Additional Dependencies

添加lib名称

执行此操作后,我收到 LNK2005 linking 错误,然后是 LNK1169。创建项目后我做的唯一一件事就是包含我试图包装的 C++ 库中的头文件。我做错了什么?

error LNK2005: "public: virtual char const * __cdecl std::exception::what(void)const " (?what@exception@std@@UEBAPEBDXZ) 已经定义在... 致命错误 LNK1169:找到一个或多个多重定义的符号

您可能正在尝试 link 静态地使用标准库的两个不同版本。您是否与库的第三方提供商核实过,以确定他们用于构建此库的 Visual Studio/C++ 版本?

此外,在解决第三方库问题时,您应该先尝试link一个简单的命令行可执行文件,然后再尝试构建 C++/CLI 库。

是的,如果可能,您应该将本机 C++ 库静态 link 到您的 C++/CLI dll。这将使部署更容易。据推测,这将是您的 C# 应用程序将使用的唯一 C++/CLI 程序集。

的确,我们是图书馆的创造者,经过长期的斗争,我们能够弄清楚这个问题。如果它对其他人有用,答案就在这里。

库是使用 CMake 生成的,为了避免手动导出符号(使用 __declspec(export),我们只是打开

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS on)

然而,在 DLL 中这样做意味着 Visual Studio 不仅导出 DLL 本身定义的符号,而且导出其继承的依赖项(例如整个 STL)。

前面的(我不太确定为什么)不是问题,因为您将链接此库作为构建可执行文件的一部分(因为我们确实有一个成功使用此 DLL 的 C++ EXE),但是如果您将 DLL 链接到另一个 DLL(CLI/C++ 就是这种情况,您基本上是在创建一个 DLL 来包装另一个 DLL),这是一个主要问题。在后者中,CLI DLL 也会尝试从系统导入符号,导致之前显示的重定义:

error LNK2005: "public: virtual char const * __cdecl std::exception::what(void)const " (?what@exception@std@@UEBAPEBDXZ) already defined in ... fatal error LNK1169: one or more multiply defined symbols found

检查这一点的一种方法是查看由基本 C++ DLL(不是 CLI 的)生成的导出文件 (.def),它包含 std::exception::what(以及许多其他内容),尽管该 DLL 从未自行定义它。

所以解决方案很简单:

  1. 关闭 CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
  2. Export/import 显式地从 DLL 中获取所需的符号(使用 __declspec(export|import).