2010-08-30 84 views
5

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

+0

另请参阅http://stackoverflow.com/questions/1778111/whats-the-differences-between-dll-lib-h-files – dyp 2010-08-30 11:02:32

回答

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文件中的信息是多余的。)。注意:当使用此方法时,无法使用新的.lib文件重建项目来更改整个DLL。某些结构更改会影响DLL中函数的地址,请参见this SO answer
通过__declspec使用Win32 API(LoadLibrary ...)和MSVC方法之间的最后一个区别是DLL的加载。当你使用LoadLibrary的时候,DLL当然是在运行时加载的(所以你可以在发现异常的时候发现它,等等)。另一种方法在加载时加载DLL,所以当Windows无法找到DLL时,程序将终止(不会运行)。

在VS中创建项目时,可以激活向导(Win32项目)结尾处的“导出符号”复选框。这给你一些导出符号的例子。此外,它引入了一个宏加一个预处理defition加上一些指令是非常有用的:


// 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并解析符号名称。

+0

+1。希望我可以多投这个票。 – 2012-11-29 21:40:46

+1

应该指出,还有一些被称为“导入库”检查http://stackoverflow.com/questions/3573475/how-does-the-import-library-work-details – 2016-09-08 22:49:22

+0

@WakanTanka是的,这是。我在我的回答中谈到了.lib。感谢您的链接。 – dyp 2016-09-09 10:24:40