【问题标题】:.h, .dll and .lib confusion.h、.dll 和 .lib 混淆
【发布时间】:2010-08-30 08:38:51
【问题描述】:

我是 vc++ 的新手。我刚刚构建了一个软件,它生成了一个 .dll 和一个 .lib。我需要在我的代码中使用这个函数。我需要链接到 .lib 和 .dll 来构建我的代码吗?我必须更改哪些项目属性才能进行此链接?

【问题讨论】:

标签: visual-c++


【解决方案1】:

实际上,您只需要 .dll 文件。它包含运行其功能所需的所有代码和数据。它还包含一个表,该表链接了函数的符号名称(例如函数 PrintMe)、它们的序号(DLL 中该函数的编号)以及它们在 DLL 中的地址。
如果您只想使用 DLL,则必须“手动”解析符号:
假设您要使用 DLL 的函数 PrintMe。您需要做的是将它的名称 (PrintMe) 或它的序号(PrintMe 是 DLL 的第一个函数)解析为它的地址。为此,您可以使用 Win32 API(又名 Windows SDK)中的 LoadLibrary、GetModuleHandle 和 GetProcAdress。此外,此方法允许您在运行时加载 DLL(见下文)。

更简单的方法是使用 MSVC(++) 功能 __declspec(dllexport) 和 __declspec(dllimport),例如


// your DLL
__declspec(dllexport) void PrintMe()
{
    printf("Hello World!");
}

// you project to use the DLL
__declspec(dllimport) void PrintMe();

第一个(dllexport)告诉编译器导出函数。第二个(dllimport)很有趣:它创建了所有必要的代码,以便能够使用 DLL 中的函数。
为此,您需要项目中的 .lib 文件(要使用 DLL)。 .lib 文件包含链接器将符号名称 (PrintMe) 解析为其在 DLL 中的地址的信息。由于 .lib 是静态绑定的,因此链接器可以使用它 - 相反,DLL 在运行时/加载时绑定,因此链接器无法使用它。 (是的,.lib 文件中的信息是多余的。)。注意:使用此方法时,您无法更改整个 DLL,而无需使用新的 .lib 文件重新构建项目。某些结构更改会影响 DLL 中函数的地址,请参阅this SO answer
使用 Win32 API (LoadLibrary...) 和通过 __declspec 的 MSVC 方法之间的最后一个区别是 DLL 的加载。当您使用 LoadLibrary 时,DLL 是在运行时加载的,当然(因此您可以在找不到异常时捕获异常等等)。另一种方法在加载时加载 DLL,因此当 Windows 找不到 DLL 时,您的程序将终止(不会运行)。

当您在 VS 中创建项目时,您可以在向导(Win32 项目)结束时激活“导出符号”复选框。这为您提供了一些导出符号的示例。此外,它还引入了一个宏、一个预处理器定义以及一些非常有用的指令:


// DLL header

#ifdef _YOUR_DLL_EXPORTS
#define YOUR_DLL_API __declspec(dllexport)
#else
#define YOUR_DLL_API __declspec(dllimport)
#endif

YOUR_DLL_API PrintMe();

您现在可以使用此头文件来构建您的 DLL,因为您的 DLL 项目具有 _YOUR_DLL_EXPORTS 定义(请参阅项目属性页、C++、预处理器)。使用 DLL 的项目也可以使用这个头文件,但不能定义这样的名称。当您在要在其中使用 DLL 的项目中包含头文件时,宏将解析为 __declspec(dllimport)。这指示链接器查找此函数(在 .lib 文件中找到)并创建所有必要的代码以在运行时加载 DLL 并解析符号名称。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-19
相关资源
最近更新 更多