我需要分发一个头文件和一个带有 DLL 的 lib 文件吗?
Do I need to distribute a header file and a lib file with a DLL?
我正在为客户更新 DLL,并且由于公司政治等原因,我的公司决定不再与客户共享源代码。
之前。我假设他们拥有所有源代码并将其作为 VC++6 项目导入。现在他们将不得不 link 到预编译的 DLL。我想,至少,我需要将 *.lib
文件与 DLL 一起分发,以便可以定义 DLL 入口点。但是,我还需要分发头文件吗?
如果我可以不分发它,客户将如何将 DLL 导入到他们的代码中?
However, do I also need to distribute the header file?
是的。否则,您的客户将不得不自己手动声明这些功能,然后才能使用它。正如您所想象的那样,这将非常容易出错并且是调试的噩梦。
是的,您需要将 header 连同您的 .lib 和 .dll
为什么?
至少有两个原因:
- 因为 C++ 需要知道库中函数的 return 类型和参数(粗略地说,大多数编译器使用 name mangling,将 C++ 函数签名映射到库入口点) .
- 因为如果您的库使用 类,C++ 编译器需要知道它们的布局才能在您的库客户端中生成代码(例如,要在堆栈上放置多少字节用于参数传递)。
补充说明:如果你问这个问题是因为你想对 header 隐藏实现细节,你可以考虑pimpl idiom。但这需要对您的代码进行一些重构,并且还会对性能产生一些影响,因此请仔细考虑
除了其他人对header/LIB文件的解释外,这里还有不同的观点。
客户无论如何都可以使用 Dependency Walker 等基本工具对 DLL 进行逆向工程,以查明您的 DLL 使用的是哪些系统 DLL,您的 DLL 使用了哪些函数(例如来自 AdvApi32.DLL).
如果您希望您的 DLL 隐藏,您的 DLL 必须:
- 动态加载所有自定义 DLL(如果不可能,无论如何做下一步)
- 在您要调用的所有函数上调用
GetProcAddress
(例如 ADVAPI32.DLL
中的 GetProcessToken
这样,至少 dependency walker(没有跟踪)将无法找到正在使用的函数(或 DLL)。您可以按顺序加载系统 DLL 的函数,而不是按名称加载,因此在 DLL 中通过文本搜索进行逆向工程变得更加困难。
调试器仍然能够调试您的 DLL(以及其他工具)并对它进行逆向工程。您需要找到防止调试 DLL 的技术。例如,最基本的 API 是 IsDebuggerPresent
。还有其他高级方法可用。
我为什么要说这些?好吧,如果您打算 不 交付 header/DLL,客户仍然能够找到导出的函数并使用它。作为 DLL 提供者,您还必须为其提供编程元素。非要躲就躲得彻底
您可以使用的一种替代方法是仅传递 DLL 并让客户使用 LoadLibrary() + GetProcAddress()。尽管您仍然需要让您的客户知道 DLL 中函数的签名。
这里有更详细的示例:
Dynamically load a function from a DLL
我正在为客户更新 DLL,并且由于公司政治等原因,我的公司决定不再与客户共享源代码。
之前。我假设他们拥有所有源代码并将其作为 VC++6 项目导入。现在他们将不得不 link 到预编译的 DLL。我想,至少,我需要将 *.lib
文件与 DLL 一起分发,以便可以定义 DLL 入口点。但是,我还需要分发头文件吗?
如果我可以不分发它,客户将如何将 DLL 导入到他们的代码中?
However, do I also need to distribute the header file?
是的。否则,您的客户将不得不自己手动声明这些功能,然后才能使用它。正如您所想象的那样,这将非常容易出错并且是调试的噩梦。
是的,您需要将 header 连同您的 .lib 和 .dll
为什么?
至少有两个原因:
- 因为 C++ 需要知道库中函数的 return 类型和参数(粗略地说,大多数编译器使用 name mangling,将 C++ 函数签名映射到库入口点) .
- 因为如果您的库使用 类,C++ 编译器需要知道它们的布局才能在您的库客户端中生成代码(例如,要在堆栈上放置多少字节用于参数传递)。
补充说明:如果你问这个问题是因为你想对 header 隐藏实现细节,你可以考虑pimpl idiom。但这需要对您的代码进行一些重构,并且还会对性能产生一些影响,因此请仔细考虑
除了其他人对header/LIB文件的解释外,这里还有不同的观点。
客户无论如何都可以使用 Dependency Walker 等基本工具对 DLL 进行逆向工程,以查明您的 DLL 使用的是哪些系统 DLL,您的 DLL 使用了哪些函数(例如来自 AdvApi32.DLL).
如果您希望您的 DLL 隐藏,您的 DLL 必须:
- 动态加载所有自定义 DLL(如果不可能,无论如何做下一步)
- 在您要调用的所有函数上调用
GetProcAddress
(例如ADVAPI32.DLL
中的GetProcessToken
这样,至少 dependency walker(没有跟踪)将无法找到正在使用的函数(或 DLL)。您可以按顺序加载系统 DLL 的函数,而不是按名称加载,因此在 DLL 中通过文本搜索进行逆向工程变得更加困难。
调试器仍然能够调试您的 DLL(以及其他工具)并对它进行逆向工程。您需要找到防止调试 DLL 的技术。例如,最基本的 API 是 IsDebuggerPresent
。还有其他高级方法可用。
我为什么要说这些?好吧,如果您打算 不 交付 header/DLL,客户仍然能够找到导出的函数并使用它。作为 DLL 提供者,您还必须为其提供编程元素。非要躲就躲得彻底
您可以使用的一种替代方法是仅传递 DLL 并让客户使用 LoadLibrary() + GetProcAddress()。尽管您仍然需要让您的客户知道 DLL 中函数的签名。
这里有更详细的示例:
Dynamically load a function from a DLL