分发Windows C ++库:如何决定是创建静态库还是动态库?

时间:2013-08-02 18:45:53

标签: c++ shared-libraries static-libraries

我们一直在将Java和.NET API库转换为C ++,并且正在尝试找出将编译版本分发给其他开发人员以与其自定义应用程序一起使用的最佳方法。它应该是静态库还是动态库?

我们需要为Win32和Win64创建(我想每个目标操作系统的Debug和Release版本)。鉴于我遇到的所有挫折都试图确保所有引用的库都匹配(/ MT与/ MD),我想知道是否有决定在这里制作,这将为其他开发人员简化它。

当我在静态库上运行dumpbin /all <static library file name> | find /i "msvc时,我没有看到任何运行时引用(与我在.exe或.dll上执行相同操作时不同)。这是否表明运行时尚未链接,这使开发人员在开发和构建自己的应用程序时能够更灵活地制作/ MT或/ MD?

哪种方法可以让开发人员的生活更轻松?

2 个答案:

答案 0 :(得分:4)

静态库更容易创建,但很多更难分发。客户端程序员将把它们链接到他的程序中,因此编译设置与他的兼容非常重要。您必须至少分发4个版本,对应4个不同的CRT版本(/ MD,/ MDd,/ MT,/ MTd)。并且您需要将其乘以常用的Visual Studio版本的数量。如果您不知道客户端程序员将要使用什么,那么这可能是一个非常大的列表。

DLL没有问题,你只为导出的函数声明提供一个.h,一个.lib,它是DLL的导入库(没有代码,只包含名称)和.dll本身。

然而,为您的DLL创建可从任何C或C ++编译器使用的接口更难。您不能公开任何标准C ++库类,返回std :: string不会起作用。您无法创建任何分配调用者需要释放的内存的函数。通常不能跨越边界抛出异常。执行任何这些操作往往会导致很难诊断客户端程序员的运行时问题,这是由内存分配器和类对象布局差异不匹配引起的。 COM对象模型就是这种接口的一个例子。

这不是您使用静态库时遇到的问题。有点不小心,他们要求运行时和编译器版本匹配。如果客户端程序员遇到了一个错误的静态库,那么他也会遇到所有这些问题。和更多。静态图书馆就像青少年性行为。你犯了一个错误,并在你的余生中最终支持它。

答案 1 :(得分:3)

静态和动态(共享)库都有显着优势。也许您可以选择分发两种类型的库,并让库用户决定使用哪种库。

对于我自己,我通常使用静态库,除非我认为动态库的优点对项目有意义。

静态库的优点之一:

  • 一旦库的用户在编译时链接,库中的代码总是在需要调用它的同一模块中。所以没有DLL地狱,没有并排的地狱。我无法计算我尝试在Windows上运行程序的次数,因为我没有安装正确版本的MSVC运行时(DLL)。这真是一种痛苦,如果可以避免,它会让每个人的生活更轻松。
  • 同样,库中代码的符号最终会出现在调用库的模块的.pdb中,而不是在你必须跟踪的另一个.pdb(.dll的.pdb)中。 ,复制等等。
  • 这是次要的,但对于静态库,只需要链接它所需的函数/数据最终会在可执行文件中。而对于DLL,它是整个enchilada。

动态库的优点

  • 显而易见的优点是,它允许在运行时替换库,即使是最终用户也可以在不重新链接的情况下进行替换。
  • 在大多数环境中这是次要的,但是如果很多可执行文件链接到库中,拥有DLL意味着更少的磁盘空间,因为在每个可执行文件中都不会重复相同的数据/代码。
  • 一些不值得欣赏的东西:如果该库将由多个进程同时加载,将其作为DLL提供 - 理想情况下 - 只有一个副本只读数据(甚至是可写数据,除非由特定进程写入,否则需要在内存中)。运行时链接DLL的所有进程在内存中共享相同的字节。共享的内存是 总虚拟内存(RAM +页面文件)物理内存。然而,这只是最好的情况 - 如果DLL无法在两个进程中加载​​到同一个虚拟地址,则无法共享它。