2011-04-22 94 views
2

我知道,如果我链接到我的C++程序到使用不同版本的Visual Studio构建的动态库(DLL),也不会因为二进制兼容性问题的工作。 (我已经经历了这与升压库和VS 2005年和2008年)C++动态库编译/链接

但我的问题是:这是真的所有版本的MSVS?这是否也适用于静态库(LIB)?这是GCC & Linux的问题吗?最后如何将VS链接到使用MinGW构建的DLL中?

通过除了跨平台或跨编译器的方式,为什么不能在两个版本相同的编译器(VS)的是compatibile?

+0

可能重复http://stackoverflow.com/questions/5728116/can-i-link-object-files-由另一个制作而成的编译器) – AProgrammer 2011-04-22 16:28:59

+1

据我所知,MS从来没有通过改变ABI来改变向后兼容性,所以我认为兼容性问题在这里是一个红鲱鱼。虽然这并不是说你可能因DLL不兼容而导致['DLL hell'](http://en.wikipedia.org/wiki/DLL_hell)。你也需要看你连接的DLL的类型。如果您的应用程序是多线程调试,则需要链接到相应DLL的多线程调试版本。 – 2011-04-22 17:42:28

回答

2

嗨。我知道,如果我将我的C++程序链接到使用不同版本的Visual Studio构建的动态库(DLL),由于二进制兼容性问题,它不起作用。 (我已经体验过Boost库和VS 2005和2008)

我不记得曾经看到MS更改过ABI,下面))。

因此,我不认为这不是Dev Studio中的不兼容性,而是Boost中的变化。
不同版本的boost不是向后兼容的(在二进制中,它们是向后兼容的源)。

但我的问题是:这是真的所有版本的MSVS?

我不相信有一个问题。现在,如果使用不同的标志,可以使对象文件不兼容。这就是为什么调试/发布二进制文件被构建到单独的目录中并与不同版本的标准运行时间链接的原因。

这是否也适用于静态库(LIB)?

您必须链接正确的静态库。但是一旦静态库存在于你的代码中,那么所有已解析的名称将不会在以后重新解析。

这是GCC & Linux的问题吗?

是。海湾合作委员会已经在几次(几个目的(有些是错误的))中逆转了ABI的兼容性。这不是一个真正的问题,因为Linux代码通常作为源代码分发,并且在您的平台上编译它,它将起作用。

最后如何将VS链接到用MinGW构建的DLL?

对不起,我不知道。

顺便说一句,除了跨平台或交叉编译器,为什么同一个编译器(VS)的两个版本不兼容?

充分优化的代码对象可能会被压缩得更多,因此对齐是不同的。其他编译器标志可能会影响与其他二进制对象不兼容的代码生成方式(改变函数调用方式(堆栈中的所有参数或寄存器中的某些参数))。从技术上讲,只有使用完全相同标志编译的对象应该连接在一起(从技术上讲,它比稍微宽松一点,因为很多标志不会影响二进制兼容性)。

注意某些库与多个版本的相同库以不同方式编译发布。你通常在扩展名结尾区分库。在我上一份工作中,我们使用了以下约定。

libASR.dll // A Sincgle threaded Relase version lib 
libASD.dll // A Single threaded Debug version 
libAMR.dll // A Multi threaded Release version 
libAMD.dll // A Multi threaded Debug version 
的[我可以链接一个编译做出那些由另一人造物的文件吗?(
+0

“这不是一个真正的问题,因为Linux代码通常作为源代码发布”< - 我认为这些日子不是这样。大多数人从二进制软件包安装软件。 – 2011-04-22 18:41:45

+0

非常感谢! 所以你说,如果我在VS2010中使用预构建的VS2008 Qt库,并且它不起作用,那是因为这些库是使用不同的标志/优化构建的,并且它不是VS或其C++的向后兼容性问题运行时库? – p00ya00 2011-04-22 18:47:03

+1

@TamásSzelei:在大多数系统中,我使用的包管理系统与源代码不是二进制的。 apt-get例如下载编译和安装。正如perl安装程序等。我确信软件包是以二进制格式提供的,但我认为这是例外情况,而不是Linux上的规则。 – 2011-04-22 18:55:16

0

如果构建得当,DLL应该是编程语言和版本中立的。您可以链接到与VB,C,C++内置的DLL等

您可以使用dependency walker检查在DLL导出的函数。

0

要回答你的问题的一部分,GCC/Linux没有这个问题。至少,不是经常。 libstdC++和glibc是GNU系统上的标准C++/C库,这些库的作者会尽力避免破坏兼容性。 glibc几乎都是向后兼容的,但libstdC++在过去几次打破ABI,并且可能在未来再次打破ABI。

它是非常与C相比,C++中编写稳定的ABI很困难,因为C++中的自动功能会带走您维护ABI所需的一些控制。特别是当你进入模板和内联函数时,其中一些代码被嵌入到应用程序中,而不是保留在共享库中。这意味着如果不需要重新编译应用程序,对象的结构就不会改变。

实际上,这在Windows上并不是什么大事。如果微软只是让MSI安装程序知道如何在安装需要它们的应用程序时从Windows Update获取微软提供的DLL,但是简单地将可再发行组件添加到InnoSetup生成的安装程序就足够了。

+0

我可能是错的,但MS从来不知道破坏ABI。另一方面GCC已经做了好几次。这就是OpenSource作为源代码发布的原因。 – 2011-04-22 17:39:47

+0

@Martin - 自3.4(2004)以来,GCC ABI一直没有变化,而MSVC在每个主要版本中都打破了它的ABI。请参阅[将Visual C++代码移植到Visual Studio 2005](http://www.devx.com/cplus/10MinuteSolution/28908/1954)。 – aponomarenko 2011-04-22 21:43:29

+0

@ user720860:我没有看到任何ABI更改,本文是关于将DevStudio与标准C++内联。如果你编写非对称C++,那么你不应该期望你的代码是可移植的(更不用说可升级了),所以在那里没有太大的意外。 GCC 3.2(变更)3.3(变更)3.4(变更)。 – 2011-04-25 07:33:03