如何在MSVC中使用MingW编译的库?

时间:2010-03-27 15:11:59

标签: c++ mingw visual-c++ compatibility static-libraries

我用MingW / MSYS编译了几个库......生成的静态库总是.a文件。 当我尝试将库与MSVC项目链接时,Visual Studio会抛出“未解析的外部符号”......这意味着.a静态库与MS C ++链接器不兼容。我认为它必须转换为兼容MSVC的.lib文件。

.a和.lib只是.o或.obj文件的AR档案,那么有什么方法可以在MSVC项目中使用MingW编译的库吗?或者我是否必须在一个编译器/链接器中编译/链接所有内容 - 仅限MSVC / MingW? 据说MingW编译器与MSVC兼容。

我读了一些关于这个主题的主题,但是他们大多说将文件重命名为.lib应该可以完成这项工作,但不幸的是,这对我不起作用。

我试图链接的库是用C语言编写的。

MSVC Linker会抛出错误,如:

error LNK2019: unresolved external symbol "int __cdecl openssl_call(struct ssl_State *,int,int,int)" (?openssl_call@@YAHPAUssl_State@@HHH@Z) referenced in function _main MyAPP.obj

...还有4个相同的错误,指的是从我的应用程序调用的其他函数。

感谢您的任何建议。

4 个答案:

答案 0 :(得分:11)

根据此错误,您会发表评论:

  

错误LNK2019:未解析的外部   符号“int __cdecl   openssl_call(struct ssl_State   *,int,int,int)“(?openssl_call @@ YAHPAUssl_State @@ HHH @ Z)   在函数_main MyAPP.obj中引用   所有其他4个错误仅相同   其他功能名称

尝试将extern "C"放在openssl的include文件周围。例如:

extern "C" {
include "openssl.h"
}

使用extern "C"将指示编译器函数使用C链接,而不是C ++,这将阻止它对函数执行name mangling。所以它会在库中寻找openssl_call函数而不是?openssl_call @@ YAHPAUssl_State @@ HHH @。

答案 1 :(得分:10)

库是兼容的,但仅限于提供C接口。 MSVC和g ++使用不同的名称修改方案,因此您无法轻松地将创建的C ++代码与另一个创建的代码链接起来。

答案 2 :(得分:7)

我介绍了在MSVC中使用mingw编译的dll的相同情况。我使用以下工具使其工作:
1)使用gcc:

  

gcc -shared -o your_dll.dll your_dll_src.c -Wl, - output-def,your_dll.def

粗体指定gcc将生成一个脚本导出项目的* def文件。然后你需要使用与MSVC一起发布的lib.exe,例如:

  

lib /def:your_dll.def

然后,会有一个来自lib.exe的your_dll.lib文件。(假设you_dll.dll与your_dll.def位于同一目录中)。

目前,我可以在我的MSVC项目中使用* .lib并正确链接dll,但是我遇到了运行时错误。无论如何,这样的工作使你的联系可行。

答案 3 :(得分:0)

简介

使用不同的编译器甚至是同一编译器的不同版本创建的目标文件和静态库通常无法链接在一起。这个问题不是MinGW特有的:许多其他编译器互不兼容。如果可以,请使用相同版本的相同编译器从源代码构建所有内容。

Dll稍有不同。有时,您可以将使用一个编译器生成的DLL链接到使用另一个编译器编译的应用程序。如果DLL是用C编写的,即使应用程序是用C ++编写的,这也能很好地工作。例如,MinGW C ++程序通常链接到Windows随附的C运行时库。只要您仅通过用extern“ C”声明的C接口与它们进行通信,用C ++编写的DLL也可以工作。否则,可能会出现链接器错误,因为不同的编译器对C ++名称的处理方式不同。

为什么不同的编译器可能无法互操作

有时人们会怀疑为什么编译器编写者不只是使用相同的名称处理方案。这可能使链接成功,但很可能会为您提供一个在您调用DLL时崩溃的程序。真正的链接兼容性需要一个通用的应用程序二进制接口,而名称处理只是其中的一个考虑因素。这是部分列表:-

如果同一系统的两个C ++实现使用不同的调用 序列,或以其他方式与链接不兼容, 使用相同的类型签名编码是不明智的。

实现者传统上使用故意不同的名称处理方案,认为在链接时“只说不”比使一些简单的代码起作用并让问题在运行时出现要好。

即使GNU g ++现在可以链接MSVC C ++库,并且可以生成与MSVC ++兼容的库/ DLL,但这并不意味着它们由于C ++的动态特性而可以在运行时工作。造成这种情况的一些可能原因是:-

  • 一个简单的名称处理问题,可能可以通过显式的.def文件来规避。
  • 不同的结构对齐问题,需要正确的编译器选项(-mms-bitfields,...)。
  • 基础异常和内存模型的根本冲突:-
  1. MSVC DLL中的new / delete或malloc / free不会与Cygwin newlib new / delete或malloc / free合作。根本无法释放使用其他new / malloc在函数中分配的空间。
  2. Cygwin可执行文件不会捕获MSVC DLL引发的异常,反之亦然。
  3. 慢速GNU SJLJ异常模型(在GCC-3.x和更早版本中使用)与MSVC ++模型兼容,但是新的DWARF2模型(将由GCC-4.x使用)将与不兼容。

参考:http://www.mingw.org/wiki/Interoperability_of_Libraries_Created_by_Different_Compiler_Brands