【问题标题】:Linking error while in C++/CLI project while wrapping C++ shared library包装 C++ 共享库时在 C++/CLI 项目中出现链接错误
【发布时间】:2018-09-12 05:15:03
【问题描述】:

我正在尝试将 C++ 库包装到托管项目可以使用它。我使用的第三方库是共享库。它旨在链接加载时间。我有头文件,.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 链接错误,然后是 LNK1169。创建项目后我做的唯一一件事就是包含我试图包装的 C++ 库中的头文件。我做错了什么?

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

【问题讨论】:

  • 你想使用库statically or dynamically吗?
  • 我很乐意使用任何方式。在 C++/CLI 项目中做这件事的首选方式是什么?我正在尝试通过使用 .lib 文件来使用静态方式,但出现奇怪的 LNK2005 错误。错误 LNK2005:“public: virtual char const * __cdecl std::exception::what(void)const” (?what@exception@std@@UEBAPEBDXZ) 已在 ....中定义。
  • 您的库是如何编译的,您目前如何尝试链接它?在没有看到您的代码的情况下,我最好的猜测是您静态编译它并尝试动态链接它。至于在 C++/CLI 库中执行此操作的首选方式,我很确定这取决于您和您的需求,如果我没记错的话,没有首选方式,只要您不尝试动态链接静态编译的库,反之亦然。
  • 您收到这些错误是因为您尝试将 C++ 库静态链接到 C# 程序。你之前有tried making a Managed C++ Wrapper?吗?
  • 我认为回答这个问题的唯一方法是写一个详尽的教程,你可能应该在谷歌上搜索一些。 (这并不是说它一定是 OT,但你可能会更快地找到一个真正的教程,而不是等待有人在这里写它。)

标签: c++ c++-cli native word-wrap


【解决方案1】:

确实,我们是图书馆的创造者,经过长时间的战斗,我们能够找出问题所在。如果它对其他人有用,这里有答案。

该库是使用 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 DLL)生成的导出文件 (.def),它包含 std::exception::what(以及许多其他),尽管该 DLL 从未定义它自己。

所以解决方案相当简单:

  1. 关闭CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS。
  2. 从 DLL 中显式导出/导入所需的符号(使用 __declspec(export|import)。

【讨论】:

  • 伟大的工作伙伴。感谢您的解释和解决问题。
【解决方案2】:

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

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

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

【讨论】:

  • 我在共享库中使用的第三方库。这意味着链接加载时间。我有头文件,.lib 文件,它是 DLL 导入库和 .DLL 文件。到目前为止,我所做的一切如下:- 1. 在 C/C++ 中设置“附加包含目录”,以便我们可以找到包含文件。 2. 在链接器->常规选项中设置“附加库目录”。 3. 在 Linker->Input setting 的 'Additional Dependencies' 中设置 lib 的名称。当我在我的项目中包含第三方头文件时,我得到了上面提到的这个 LNK2005 错误。不知道怎么回事!!
  • 您是否检查了供应商用于构建共享库的编译器。您是否尝试链接一个简单的 C++ 命令行测试程序?
  • 他们使用 CMake 2.8 来生成库。我在库的头文件中看不到 dllexport/import,但似乎 cmake 的新功能允许您导出函数而无需指定 dllexport/import。构建文件显示他们正在使用“Visual Studio 15 2017 Win64”来构建它。我尝试使用 Visual Studio 2015 和 2017 链接它失败。它在没有 CLR 支持的情况下链接正常。这能告诉我们什么吗?我有一种感觉,他们缺少一些东西,但我不确定什么,因为我对使用 cmake 构建库一无所知。
  • 好的,所以他们用 VS 2017 构建了它(15 是 VS 20170 的版本号)。它在没有 CLR 支持的情况下构建的事实表明您使用的是兼容的编译器,但您的 CLR 配置存在问题。你是在 64 位模式下构建你的 CLR dll 吗?您在构建 C++ 代码时是否使用 /MD 标志?
  • 是的。我已将平台设置为 x64。并且 flag 也设置为 /MD,这是我创建 clr 项目时的默认设置。设置任何其他标志会导致不兼容的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多