函数库:把函数组织起来,供其他程序调用,达到函数的复用的目的。
1、静态函数库与动态函数库:
静态函数库 - 编译时代码直接被编译链接到exe中。
缺点:会使程序的体积非常庞大。不利于模块的共享。
优点:不会产生dll文件,不依赖dll文件就能运行。
动态函数库 - 就是把函数或业务代码封装在dll文件中。
优点:函数代码在dll文件中,其他程序可以调用dll中的代码,可以被多个程序共享。
缺点:生成的exe文件依赖dll,容易导致dll hell问题。
建议:哪怕不需要被其他程序共享,在大型工程中建议通过dll的方式来组织函数,
减少单个exe的体积并且有利于开发人员的分工合作。
2、编写dll。
打开vc++ 6.0 在工程中选择 win32 dynamic link library。
在想要被外部函数调用的前加上extern “c” __declspec(dllexport) 或 __declspec(dllimport) int add(int a, int b);
这样才能被其他程序通过dll的方式调用。
示例代码如下:
#include
#include
__declspec(dllexport) int add(int a, int b)
{
return a + b;
}
__declspec(dllexport) int sub(int a, int b)
{
return a - b;
}
BOOL APIENTRY DllMain(
HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if(ul_reason_for_call == DLL_PROCESS_ATTACH)
{
printf("dll is loaded!");
}
}
3、调用。
a、静态链接:把dll和lib复制到需要调用dll的工程目录下。
#pragma comment(lib, “lib库名”)
用extern “c” __declspec(dllexport) int add(int a, int b);
__declspec(dllimport) int add(int a, int b);
然后就可以像调用普通函数一样调用了。
示例代码如下:
#include
#pragma comment(lib, "dllDemo.lib")
__declspec(dllimport) int add(int a, int b);
__declspec(dllimport) int sub(int a, int b);
int main(void)
{
int a = 10, b = 5;
printf("a + b = %d\n", add(a, b));
printf("a - b = %d\n", sub(a, b));
return 0;
}
b、动态链接。
–>声明一个函数指针:
typedef int (__cdecl* fpAdd)(int, int);
–>声明一个HMODULE hModule;用来保存加载dll文件的句柄
再用函数指针声明一个变量,如:fpAdd add;
hModule = LoadLibrary("1.dll");//可以是绝对路径也可以是相对路径
if(hModule == NULL)
{
//error
}
add = (fpAdd)GetProcAddress(hModule, "add");
if(NULL == add)
{
//error
}
int r = add(1, 2);
FreeLibrary(hModule); //释放句柄
示例代码如下:
# include
# include
# include
typedef int (*fun)(int , int);
int main(void)
{
int a = 10, b = 5;
HINSTANCE dllDemo = LoadLibrary("dllDemo.dll");
fun add, sub;
if (dllDemo)
{
add = (fun)GetProcAddress(dllDemo, "add");
sub = (fun)GetProcAddress(dllDemo, "sub");
}
else
{
printf("Fail to load dll\n");
system("pause");
exit(1);
}
printf("a + b = %d\n", add(a, b));
printf("a - b = %d\n", sub(a, b));
system("pause");
return 0;
}
静态链接与动态链接的区别:
静态链接库在程序启动的时候就会去检查dll释放存在,如果不存在在启动的时候
就会报错,程序无法启动;动态链接库时在运行到的时候才会去检查dll是否存在
,而且可以由程序员决定在dll不存在的时候判断逻辑。
要区分静态库、动态库。dll静态调用和动态调用:
dll静态调用和动态调用是动态库的两种调用方式。