| 分类: c++ |
VC++:动态链接库的静态调用和动态调用的区别及实例
假设已经建立test.dll文件,里面封装的函数是int add(int,int)
一、静态调用
#pragma comment(lib, "dlltest.lib")
extern "C" _declspec(dllexport) int add(int i1,int i2);
*****
int i = add(10,20);
TCHAR str[256];
itoa(i, str, 10);
MessageBox(hwnd,str,TEXT("问好"),MB_OK);
预声明后,代码内直接调用.
二、动态调用
typedef int(__cdecl* FunctionAdd)(int,int); //函数指针
。。。。。
HMODULE hModule;
FunctionAdd add;
//LoadLibrary返回的是dll文件的句柄
hModule = LoadLibrary("dlltest.dll");
if(NULL== hModule )
{
MessageBox(hwnd, TEXT("没有dll文件"), TEXT(""), MB_OK);
return;
}
add =(FunctionAdd)GetProcAddress(hModule,"add");
if(NULL==add)
{
MessageBox(hwnd, TEXT("dll文件中没有函数"), TEXT(""), MB_OK);
break;
}
int r = add(1,1);
TCHAR str[256];
itoa(r, str, 10);
MessageBox(hwnd, str, TEXT(""), MB_OK);
FreeLibrary(hModule);
要用到C语言中函数指针的知识
二者的区别:
1、静态调用时,如果exe所在的文件夹没有dll文件及其lib文件,则运行exe会报错。及exe根本就运行不起来 ,系统提示没有找到dll文件等信息。错误信息是不可控的。
2、动态调用只有再调用dll文件时,如果没有,才会报错,并且此错误时可控的。
//////////////////另一篇关于静态调用dll与动态调用dll的例子///////////
vc静态加载dll和动态加载dll
如果你有a.dll和a.lib,两个文件都有的话可以用静态加载的方式:
message函数的声明你应该知道吧,把它的声明和下面的语句写到一个头文件中
#pragma comment(lib, "a.lib")
然后你的对话框.cpp中包含这个头文件就可以使用message函数了。
如果dll没有对应的.lib文件,那么就只能使用动态加载的方式了。
动态调用动态库步骤:
1、创建一个函数指针,其指针数据类型要与调用的DLL引出函数相吻合。
2、通过Win32 API函数LoadLibrary()显式的调用DLL,此函数返回DLL的实例句柄。
3、通过Win32 API函数GetProcAddress()获取要调用的DLL的函数地址,把结果赋给自定义函数的指针类型。
4、使用函数指针来调用DLL函数。
5、最后调用完成后,通过Win32 API函数FreeLibrary()释放DLL函数。
例如:
假设函数的声明为:void message(int a);
//函数指针声明
typedef void (WINAPI MESSAGE)(int a);
MESSAGE *pMessage = 0;
//加载a.dll
HINSTANCE hDLLDrv = LoadLibrary("a.dll");
//获取message函数的指针
if(hDLLDrv)
{
pMessage = (MESSAGE *)GetProcAddress(hDLLDrv, "message");
}
然后就可以这样调用函数了:
pMessage(1);
/////////////////////////////////////////
VC中生成DLL的办法见:
www.codeproject.com/KB/DLL/RegDLL.aspx
--------------------------------------
VC中使用DLL
http://www.cnblogs.com/c1230v/articles/1401448.html
调用DLL有两种方法:静态调用和动态调用.
(一).静态调用其步骤如下:
1.把你的youApp.DLL拷到你目标工程(需调用youApp.DLL的工程)的Debug目录下;
2.把你的youApp.lib拷到你目标工程(需调用youApp.DLL的工程)目录下;
3.把你的youApp.h(包含输出函数的定义)拷到你目标工程(需调用youApp.DLL的工程)目录下;
4.打开你的目标工程选中工程,选择Visual C++的Project主菜单的Settings菜单;
5.执行第4步后,VC将会弹出一个对话框,在对话框的多页显示控件中选择Link页。然后在Object/library modules输入框中输入:youApp.lib
6.选择你的目标工程Head Files加入:youApp.h文件;
7.最后在你目标工程(*.cpp,需要调用DLL中的函数)中包含你的:#include "youApp.h"
注:youApp是你DLL的工程名。
(二).动态调用其程序如下:
动态调用时只需做静态调用步骤1.
01{
02 HINSTANCEhDllInst=LoadLibrary("youApp.DLL");
03 if(hDllInst)
04 {
05 typedefDWORD (WINAPI*MYFUNC)(DWORD,DWORD);
06 MYFUNCyouFuntionNameAlias=NULL;
07 // youFuntionNameAlias 函数别名
08 youFuntionNameAlias= (MYFUNC)GetProcAddress(hDllInst,"youFuntionName");
09 // youFuntionName 在DLL中声明的函数名
10 if(youFuntionNameAlias)
11 {
12 youFuntionNameAlias(param1,param2);
13 }
14 FreeLibrary(hDllInst);
15 }
16}
显式(静态)调用:
LIB + DLL + .H,注意.H中dllexport改为dllimport
隐式(动态)调用:
DLL + 函数原型声明,先LoadLibrary,再GetProcAddress(即找到DLL中函数的地址),不用后FreeLibrary
--------------------------------------
动态链接库DLL的链接
http://blog.donews.com/mmycly/archive/2006/06/15/917076.aspx
应用程序使用DLL可以采用两种方式:一种是隐式链接,另一种是显式链接。在使用DLL之前首先要知道DLL中函数的结构信息。Visual C++6.0在VC\bin目录下提供了一个名为Dumpbin.exe的小程序,用它可以查看DLL文件中的函数结构。另外,Windows系统将遵循下面的搜索顺序来定位DLL: 1.包含EXE文件的目录,2.进程的当前工作目录, 3.Windows系统目录, 4.Windows目录,5.列在Path环境变量中的一系列目录。
(一).隐式链接
隐式链接就是在程序开始执行时就将DLL文件加载到应用程序当中。实现隐式链接很容易,只要将导入函数关键字_declspec(dllimport)函数名等写到应用程序相应的头文件中就可以了。下面的例子通过隐式链接调用MyDll.dll库中的Min函数。首先生成一个项目为TestDll,在 DllTest.h、DllTest.cpp文件中分别输入如下代码:
01//Dlltest.h
02 #pragma comment(lib,"MyDll.lib")
03 extern"C"_declspec(dllimport) intMax(inta,int b);
04 extern"C"_declspec(dllimport) intMin(inta,int b);
05//TestDll.cpp
06#include
07#include"Dlltest.h"
08voidmain()
09{
10 inta;
11 a=min(8,10)
12 printf("比较的结果为%d\n",a);
13}
在创建DllTest.exe文件之前,要先将MyDll.dll和MyDll.lib拷贝到当前工程所在的目录下面,也可以拷贝到windows的 System目录下。如果DLL使用的是def文件,要删除TestDll.h文件中关键字extern "C"。TestDll.h文件中的关键字Progam commit是要Visual C+的编译器在link时,链接到MyDll.lib文件,当然,开发人员也可以不使用#pragma comment(lib,"MyDll.lib")语句,而直接在工程的Setting->Link页的Object/Moduls栏填入 MyDll.lib既可。
编程时用ad.h,ad.lib,放在项目当前目录里
在头文件中加入#include "ad.h"
在Project Setting–>Link–>Object/library modules加入ad.lib
执行时将ad.dll跟你的程序放在同一目录
(二).显式链接
显式链接是应用程序在执行过程中随时可以加载DLL文件,也可以随时卸载DLL文件,这是隐式链接所无法作到的,所以显式链接具有更好的灵活性,对于解释性语言更为合适。不过实现显式链接要麻烦一些。在应用程序中用LoadLibrary或MFC提供的AfxLoadLibrary显式的将自己所做的动态链接库调进来,动态链接库的文件名即是上述两个函数的参数,此后再用GetProcAddress()获取想要引入的函数。自此,你就可以象使用如同在应用程序自定义的函数一样来调用此引入函数了。在应用程序退出之前,应该用FreeLibrary或MFC提供的AfxFreeLibrary释放动态链接库。下面是通过显式链接调用DLL中的Max函数的例子。
01#include
02#include
03voidmain(void)
04{
05 typedefint(*pMax)(inta,int b);
06 typedefint(*pMin)(inta,int b);
07 HINSTANCEhDLL;
08 PMaxMax
09 HDLL=LoadLibrary("MyDll.dll");//加载动态链接库MyDll.dll文件;
10 Max=(pMax)GetProcAddress(hDLL,"Max");
11 A=Max(5,8);
12 Printf("比较的结果为%d\n",a);
13 FreeLibrary(hDLL);//卸载MyDll.dll文件;
14}
在上例中使用类型定义关键字typedef,定义指向和DLL中相同的函数原型指针,然后通过LoadLibray()将DLL加载到当前的应用程序中并返回当前DLL文件的句柄,然后通过GetProcAddress()函数获取导入到应用程序中的函数指针,函数调用完毕后,使用 FreeLibrary()卸载DLL文件。在编译程序之前,首先要将DLL文件拷贝到工程所在的目录或Windows系统目录下。
使用显式链接应用程序编译时不需要使用相应的Lib文件。另外,使用GetProcAddress()函数时,可以利用 MAKEINTRESOURCE()函数直接使用DLL中函数出现的顺序号,如将GetProcAddress(hDLL,"Min")改为 GetProcAddress(hDLL, MAKEINTRESOURCE(2))(函数Min()在DLL中的顺序号是2),这样调用DLL中的函数速度很快,但是要记住函数的使用序号,否则会发生错误。
浙公网安备 33010602011771号