静态链接库与动态链接库(下)

七、动态地加载和调用动态库中的函数

在VC中new一个名为dllCall的Win32 Console Application工程,并将上面生成的dllTest.dll文件拷贝到dllCall的工程子目录下。dllCall工程仅包含一个main.cpp文件,其源代码如下::

#include <stdio.h>

#include <windows.h>

typedef int(*lpAddFun)(int, int); //定义函数指针类型

int main(int argc, char *argv[])

{

HINSTANCE hDll; //DLL句柄

lpAddFun addFun; //函数指针变量

hDll = LoadLibrary("dllTest.dll");

if (hDll != NULL)

{

addFun = (lpAddFun)GetProcAddress(hDll, "add");

if (addFun != NULL)

{

int result = addFun(2, 3);

printf("%d", result);

}

FreeLibrary(hDll);

}

return 0;

}

下面我们来逐一分析上面的程序。

首先,语句typedef int ( * lpAddFun)(int,int)定义了一个与add函数接受参数类型和返回值均相同的函数指针类型。随后,在main函数中定义了lpAddFun的实例addFun;

其次,在函数main中定义了一个DLL HINSTANCE句柄实例hDll,通过Win32 API函数LoadLibrary动态加载了DLL模块并将DLL模块句柄赋给了hDll;

再次,在函数main中通过Win32 API函数GetProcAddress得到了所加载DLL模块中函数add的地址并赋给了addFun。经由函数指针addFun进行了对DLL中add函数的调用;

最后,应用工程使用完DLL后,在函数main中通过Win32 API函数FreeLibrary释放了已经加载的DLL模块。

上面例子中我们看到了由“LoadLibrary-GetProcAddress-FreeLibrary”系统API提供的三位一体“DLL加载-DLL函数地址获取-DLL释放”方式,这种调用方式称为DLL的动态调用方式。动态调用方式的特点是完全由编程者用Windows API 函数加载和卸载 DLL,程序员可以在运行时决定 DLL 文件何时加载或不加载,决定加载哪个 DLL 文件。

八、静态地加载和和调用动态库中的函数

与动态调用方式相对应的就是静态调用方式。静态调用方式的特点是由编译系统完成对DLL的加载和应用程序结束时 DLL 的卸载。当调用某DLL的应用程序结束时,若系统中还有其它程序使用该 DLL,则Windows对DLL的应用记录减1,直到所有使用该DLL的程序都结束时才释放它。静态调用方式简单实用,但不如动态调用方式灵活。

下面我们来看看静态调用的例子,将编译dllTest工程所生成的dllTest.lib和dllTest.dll文件拷入dllCall工程所在的路径,dllCall执行下列代码:

// 导入库dllTest.lib文件中仅仅是关于其对应的DLL文件中函数的重定位信息

#pragma comment(lib,"dllTest.lib")

extern "C" __declspec(dllimport) add(int x,int y);

int main(int argc, char* argv[])

{

int result = add(2,3);

printf("%d",result);

return 0;

}

由上述代码可以看出,静态调用方式的顺利进行需要完成两个动作:

(1)告诉编译器与DLL相对应的.lib导入库文件所在的路径及文件名,#pragma comment(lib,"dllTest.lib")就是起这个作用。

程序员在建立一个DLL文件时,连接器会自动为其生成一个对应的.lib导入库文件,该文件包含了DLL 导出函数的符号名及序号(并不含有实际的代码)。在应用程序里,.lib文件将作为DLL的替代文件参与编译。

(2)声明导入函数,extern "C" __declspec(dllimport) add(int x,int y)语句中的__declspec(dllimport)发挥这个作用。

静态调用方式不再需要使用系统API来加载、卸载DLL以及获取DLL中导出函数的地址。这是因为,当程序员通过静态链接方式编译生成应用程序时,应用程序中调用的与.lib文件中导出符号相匹配的函数符号将进入到生成的EXE 文件中,.lib文件中所包含的与之对应的DLL文件的文件名也被编译器存储在 EXE文件内部。当应用程序运行过程中需要加载DLL文件时,Windows将根据这些信息发现并加载DLL,然后通过符号名实现对DLL 函数的动态链接。这样,EXE将能直接通过函数名调用DLL的输出函数,就象调用程序内部的其他函数一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值