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

hjzp0vay  于 2022-11-19  发布在  Windows
关注(0)|答案(2)|浏览(140)

我们一直在将Java和.NET API库转换为C++,并试图找出将编译后的版本分发给其他开发人员以用于他们的自定义应用程序的最佳方式。它应该是静态库还是动态库?
我们需要为Win32和Win 64创建库(我想每个目标操作系统都有一个调试和发布版本)。考虑到我在确保所有引用的库都匹配时遇到的所有挫折(/MT与/MD),我想知道是否有一个决策可以在这里做出,这将为其他开发人员简化它。
当我在静态库上运行dumpbin /all <static library file name> | find /i "msvc时,我看不到任何运行时引用(与我在.exe或.dll上执行相同操作时不同)。这是否表明运行时尚未链接,这是否为开发人员在开发和构建自己的应用时提供了更大的灵活性来创建/MT或/MD?
哪种方法会让开发人员的工作更轻松?

dy2hfwbg

dy2hfwbg1#

静态 库 更 容易 创建 , 但 * * 更 * * 难 分发 。 客户 程序 员 将 把 它们 链接 到 他们 的 程序 中 , 所以 你 的 编译 设置 与 他们 的 兼容 是 非常 重要 的 。 你 必须 分发 至少 4 个 版本 , 与 4 个 不同 的 CRT 版本 相 对应(/MD ,/MDd ,/MT ,/MTd ) 。 您 需要 将 此 值 乘以 常用 的 Visual Studio 版本 数 。 如果 您 不 知道 客户 端 程序 员 要 使用 的 版本 , 则 可能 会 有 一 个 非常 大 的 列表 。
这 不是 DLL 的 问题 , 您 只需 为 导出 的 函数 声明 提供 一 个 . h 、 一 个 . lib ( 它 是 DLL 的 导入 库 , 没有 代码 , 只 包含 名称 ) 和 . dll 本身 。
然而 , 为 DLL 创建 一 个 可 从 任何 C 或 C + + 编译 器 使用 的 接口 是 比较 困难 的 。 你 不能 公开 任何 标准 的 C + + 库 类 , 例如 , 返回 std : : string 是 不 起 作用 的 。 你 不能 创建 任何 分配 内存 的 函数 , 这些 内存 需要 由 调用 方 释放 。 你 通常 不能 越过 边界 抛出 异常 。 做 这些 事情 中 的 任何 一 件 都会 导致 客户 程序 员 很 难 诊断 运行 时 问题 , 这 是 由 不 匹配 的 内存 分配 器 和 类 对象 布局 差异 引起 的 。 COM 对象 模型 就是 这样 一 个 接口 的 例子 。
这 不是 静态 库 的 问题 。 有些 意外 的 是 , 它们 * 需要 * 运行 时 和 编译 器 版本 匹配 。 如果 客户 端 程序 员 被 一 个 错误 风格 的 静态 库 卡住 , 那么 他们 也 会 有 所有 这些 问题 。

z6psavjg

z6psavjg2#

静态和动态(共享)库都有明显的优点。也许你的一个选择是分发这两种类型的库,让库用户决定使用哪一种。
对我自己来说,我通常使用静态库,除非我认为动态库的优点对项目有意义。
静态库的优点包括:

  • 一旦库的用户在编译时链接到库中,库中的代码总是在需要调用它的同一个模块中。因此,我已经数不清有多少次试图在Windows上运行一个程序却因为没有正确的MSVC运行时版本而失败了(DLL)安装。这真的是一个痛苦,如果它可以避免,它使每个人的生活更容易。
  • 同样地,程式库中程式码的符号会在呼叫程式库之模块的.pdb中结束,而不是在另一个.pdb(.dll的.pdb)中结束,您必须加以追踪、复制等等。
  • 这是次要的,但是对于静态库来说,只有你需要链接的函数/数据最终会出现在可执行文件中,而对于DLL来说,这就是整个的enchilada。

动态库的优点

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

相关问题