我需要分发头文件和库文件吗?这是关于DLL的问题。

6
我正在为一位客户更新DLL,由于公司政策等原因,我们决定不再与客户共享源代码。以前,我想他们拥有所有的源码并将其导入为VC++6项目。现在,他们将不得不链接到预编译的DLL。我认为,至少需要将*.lib文件与DLL一起分发,以定义DLL入口点。但是,我是否还需要分发头文件呢?如果我可以不分发它,客户该如何将DLL导入其代码中?

4
如果没有头文件,你该如何创建某个实例并调用其方法?由于所有内容都是未定义的,因此会在编译时出现错误。 - Ceros
@Ceros:那是一个答案! - Lightness Races in Orbit
为什么你们公司之前“分享了源代码”? - Ajay
4个回答

14

是的,您需要与您的.lib和.dll一起分发头文件。

为什么?

至少有两个原因:

  • 因为C++需要知道库中函数的返回类型和参数(粗略地说,大多数编译器使用名称修饰将C++函数签名映射到库入口点)。
  • 因为如果您的库使用类,C++编译器需要了解它们的布局以在库客户端中生成代码(例如,传递参数时要在堆栈上放置多少字节)。

附加说明: 如果您之所以提出这个问题是因为想从头文件隐藏实现细节,则可以考虑使用“pimpl”技法。但这将需要对您的代码进行一些重构,并且可能会在性能方面产生一些影响,因此请谨慎考虑。


名称修饰在这里并不是特别相关。你需要C头文件的原因与你需要C++头文件的原因完全相同,即使在其C ABI没有实质性地“修饰”C符号的平台上(即非VS)。在这两种情况下,你都可以在自己的代码中重新声明所有库符号,但必须有人告诉你这些符号是什么,而这就是头文件的作用! - Lightness Races in Orbit

6

然而,我也需要分发头文件吗?

是的。否则,你的客户必须手动声明函数才能使用它。可以想象,这将非常容易出错并且难以调试。


3
除了其他人解释关于头文件/LIB文件的内容,这里提供不同的视角。
客户无论如何都能够使用基本工具(例如依赖项查看器)对DLL进行反向工程,以找出您的DLL正在使用哪些系统DLL、哪些函数(例如来自AdvApi32.DLL的某些函数)。
如果您希望您的DLL被隐藏,您的DLL必须:
- 动态加载所有自定义DLL(如果不可能,仍需执行下一步操作) - 对要调用的所有函数调用GetProcAddress(例如从ADVAPI32.DLL获取GetProcessToken)
这样,至少依赖项查看器(无需跟踪)将无法找到正在使用哪些函数(或DLL)。您可以按序号加载系统DLL的函数,而非按名称加载,这样通过DLL中的文本搜索进行反向工程就更加困难。
调试器仍然能够调试您的DLL(以及其他工具)并对其进行反向工程。您需要找到防止调试DLL的技术。例如,最基本的API是IsDebuggerPresent。还有其他高级方法可用。
为什么我要说这些?因为如果您打算不提供头文件/DLL,则客户仍然能够找到导出的函数并使用它们。作为DLL提供者,您还必须提供与之配套的编程元素。如果您必须隐藏,那就彻底隐藏。

0

你可以采用的一种替代方案是仅传递 DLL,并让客户端使用 LoadLibrary() + GetProcAddress() 动态加载它。尽管如此,你仍然需要让客户端知道 DLL 中函数的签名。

这里有更详细的示例:

从 DLL 动态加载函数


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接