动态链接库的创建:
1. 需要在要导出的函数前加上关键字 _declspec(dllexport) 例如:
_declspec(dllexport) int add(int a,int b)
{
return a+b;
}
class _declspec(dllexport) ClassName //将_declspec(dllexport)放在类名前,将导出类的所有成
{ //员函数。如果放在成员函数前则只导出该成员函数。
public:
void add(int a,int b);
};
//以上方式导出时编译器将自动将函数名改编以支持函数重载,这样导出的DLL在C程序无法使用,
//为了解决这个问题必须再加上 extern "C" 关键字,以使导出时不变更函数名。例如:
extern "C" _declspec(dllexport) int add(int a,int b)
{
return a+b;
}
//如果增加函数调用约定的关键字 _stdcall,则不论是否声明过 extern "C" 都将进行函数名改编。
//例如:
extern "C" _declspec(dllexport) _stdcall int add(int a,int b)
{
return a+b;
}
//使用模块定义文件导出函数时不需要关键字 _declspec(dllexport),函数名也可以自行定义,
//推荐使用这个方法。例如:
<dll1.def>
LIBRARY dll1 //dll1是动态链接库的内部名,必须与导出的dll文件名相同
EXPORTS //导出标记
add //导出的函数名
sub=subtract //导出后的函数名=被导出的函数名
2. 编译后会生成*.lib 和*.dll 文件。
其中*.lib 文件为导出库文件,他包含了动态链接库中的函数名和变量名等信息;*.dll文件为动态链接库文件,他包含了函数的实现和变量等数据。
动态链接库的静态加载:
1. 在使用动态链接库的代码前,需要先声明函数或变量来自外部,例如:
extern int add(int ,int); //第一种方式
或者:
_declspec(dllimport) int add(int ,int); //第二种方式(推荐)
class _declspec(dllimport) ClassName
{
public:
void add(int a,int b);
};
//推荐使用第2种方式,因为他可以告诉编译器该函数来自一个dll,据说可以生成效率更高的代码。
2. 在工程中添加创建时产生的*.lib。
动态链接库的动态加载:
HINSTANCE hInst;
hInst=LoadLibrary("Dll1.dll"); //API函数加载DLL
typedef int (*ADDPROC)(int a,int b); //定义函数指针类型
ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add"); //API函数获取函数地址
/*ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));
*使用函数序号的方式获取函数地址*/
if(!Add)
{
MessageBox("获取函数地址失败!");
return;
}
Add(5,3);
FreeLibrary(hInst); //API函数释放DLL
//动态加载时不需要在工程中添加*.lib,并且使用dumpbin工具也无法看到需要的外部函数名
动态链接库的入口函数
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to the DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved // reserved
);
小技巧:
1. 可以使用dumpbin或者depends工具来查看dll导出的函数,也可以用他来查exe文件需要的外部函数。
2. 在编译dll文件时,通常提供一个头文件,例如:
<dll1.h>
#ifdef DLL1_API
#else
#define DLL1_API _declspec(dllimport)
#endif
DLL1_API int add(int a,int b);
这样在创建dll文件时做如下修改:
#define DLL1_API _declspec(dllexport)
#include "dll1.h"
int add(int a,int b) //此处不再需要_declspec(dllexport),因为已经在头文件中声明过了。
{
return a+b;
}
在使用dll文件时做如下修改:
#include "dll1.h" //添加头文件
int add(int ,int); //此处不再需要_declspec(dllimport),因为已经在头文件中声明过了。