.h,.dll和.lib混淆

时间:2010-08-30 08:38:52

标签: visual-c++

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

1 个答案:

答案 0 :(得分:10)

实际上,您只需要.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 通过__declspec使用Win32 API(LoadLibrary ...)和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并解析符号名称所需的所有代码。