【问题标题】:How do I create a Win32 DLL without a dependency on the C runtime如何创建不依赖于 C 运行时的 Win32 DLL
【发布时间】:2010-11-19 17:46:37
【问题描述】:

使用 Visual Studio 2008 及其 C/C++ 编译器,如何创建仅依赖于其他 Windows DLL 且不依赖于 Microsoft C 运行时的 Win32 DLL?

我有一些 C 代码我想放在一个完全是计算的 DLL 中,并且几乎不使用 C 库函数。

对于它确实使用的那些(例如 memcpy),我很高兴重新编写代码以使用 Win32 API 等效项(例如 CopyMemory)。

【问题讨论】:

标签: c++ c winapi dll


【解决方案1】:

使用 /NODEFAULTLIB 链接器选项并(当然)确保您对运行时没有实际依赖关系。您还必须使用 /ENTRY 链接器选项为 DLL 指定和定义自己的入口点,或者拥有与编译器/链接器期望的名称匹配的自己的入口点函数(对于 dll,即 _DllMainCRTStartup) .

Matt Pietrek 早在 LIBCTINY 上发表的文章可能包含您需要的所有信息:

【讨论】:

  • 引用那篇文章“幸运的是,我们已经过去了那些日子,在大多数情况下,您可以依赖目标计算机上的 MSVCRT.DLL。” Pietrek 建议你应该如此依赖。
  • 还是真的吗?自从 Windows 2000 时代以来发生了很多变化。我认为现在我们不应该依赖机器上的 MSVCRT。至少它比马特的陈述更复杂。
  • 我们可以依赖机器上的 MSVCRT.dll,但 Visual C++ 链接到 MSVCRver.dll,其中 ver 为 80、90、100、110 等。
【解决方案2】:

您对 CRT 的依赖可能比您想象的要多。它会拆除线程本地存储等资源,并且全局类初始化器在 main() 之前由 CRT 运行。

如某人所说,考虑使用静态 CRT 进行链接,如果您真的不想这样做,请按照其他人所说的那样使用 /NODEFAULTLIB 和 /ENTRY。

哦,与其重做 memcpy,不如考虑使用超快的compiler intrinsic。您可以使用 /Oi 打开内在函数。

【讨论】:

  • 我仅以 memcpy 为例。
  • 这是个好主意,但他们是否证明编译器的内在函数不依赖于他们自己的 C 运行时的存在?我假设我可以检查编译器输出以确定,但这比我想象的要多……
  • intrinsics 都是由编译器手工生成的程序集。但是,在重新阅读文档后,如果您告诉编译器,它并不能保证编译器会使用内部函数。例如,由于不同的性能特征,它可能仅对小于或大于特定大小的 strcpy 使用内部函数。
【解决方案3】:

对于“调试”模式试试这个:

  1. 转到项目\[项目名称] 属性...
  2. 打开配置属性
  3. 打开C/C++
  4. 打开代码生成
  5. 对于 运行时库,选择 多线程调试 (/MTd) 而不是 多线程调试 DLL (/MDd)

对于“发布”模式,除了在最后一步中选择多线程 (/MT) 之外,执行相同的步骤。

这会导致您程序中使用的任何 C 运行时函数静态链接到您的二进制文件。

【讨论】:

  • 那个对我有用。我不想删除对 MSVCRT 的依赖,而是想以某种方式“限制”可能导致“缺少依赖”错误的其他依赖。
【解决方案4】:

/NODEFAULTLIB 链接器标志实际上不是正确的标志。它将忽略所有默认库,包括uuid.lib等其他库。

您想要的是/Zl 编译器选项,“省略.OBJ 中的默认库名称”。

【讨论】:

    【解决方案5】:

    您必须确保您使用的所有 Win32 DLL 都不需要 C 运行时,否则您将回到原点。如果 Win32 DLL 之一依赖于 C 运行时,则静态编译 DLL 无关紧要。

    我可以看到这个工作的唯一方法是将所有依赖的 DLL(如果这甚至可行的话)静态链接到您的 DLL 中。这当然意味着您必须重新编译才能利用任何 DLL 更新。

    【讨论】:

      【解决方案6】:

      一些 Windows 库依赖于 C 运行时(例如 ODBC32.DLL) 所以我认为你在这里什么都没有。你为什么要这样做呢?

      【讨论】:

      • 我认为假设 windows dll 的任何依赖项都将随 windows 一起提供是公平的。我不明白你的意思。
      • 如果您的代码依赖于像 ODBC32 这样的 DLL,那么它间接依赖于 Windows 附带的 CRT - 您是否误以为它必须单独分发?如果你不赞成这个答案,我不得不问 - 为什么?
      • 如果我使用 microsoft C 编译器构建我的代码,如果我想要他们记录/支持的行为,我必须使用它提供的 C 运行时。这需要使用我的代码分发所述运行时。我想我可以“发现”另一个在 Windows 中运行的 C 运行时并以某种方式动态链接到它,但这比我想象的要多得多,尤其是当我实际上不需要它的任何功能时......
      • 您不需要随应用程序分发 C 运行时,也不需要“发现”另一个 C 运行时 - 您只需使用所有其他 Windows 应用程序都使用的那个。我有一个 FOSS 项目,它是一个单一的 Windows 可执行文件,没有任何类型的运行时分发。
      • 阅读后跟进:stackoverflow.com/questions/135296/… 自称来自MS的人的回复说明了一切。如果我想在 VC 2008 中使用 C/C++ 语言,我需要重新分发那个 msvcrt。如果我不想这样做,我可以按照你的建议去做,并获得 vc2008 的语言假设和一些旧的 msvcrt 的某种奇怪的互通,或者我可以通过根本不链接到 msvcrt 来消除歧义(编译器清楚支持)。我完全可以想象,链接到旧链接将“大部分工作”。
      【解决方案7】:

      用静态 microsoft lib 编译它。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      相关资源
      最近更新 更多