动态链接库的创建和调用方法
最近在寫dll,看了一些網(wǎng)上的資源,自己整理了一下,這里把它貼出來。好了,進(jìn)入正題。
??? 我今天要講的主要是非mfcdll,也就是win32 dynamic link library ,如下圖所示:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? 圖 ? 1
1. 一個(gè)簡(jiǎn)單的dll示例
??????????? 如圖1所示,在file菜單下new一個(gè)個(gè)Win32 Dynamic-Link Library工程,取名為simple_dll。在建立的工程中添加如下文件
/* 文件名:simple_dll.h */ #ifndef SIMPLE_DLL_H #define SIMPLE_DLL_H extern "C" int _declspec(dllexport)add(int x, int y); #endif/* 文件名:simple_dll.cpp */#include "simple_dll.h"int add(int x, int y) {return x + y; } 如上就建立了一個(gè)簡(jiǎn)單的動(dòng)態(tài)鏈接庫工程。按下F7,或者點(diǎn)擊build菜單下的build simple_dll.dll可以在debug文件夾下生成simple_dll.lib和simple_dll.dll文件。
接下來我們編寫一個(gè)win32 console application工程調(diào)用dll中的add函數(shù)。在文件菜單下點(diǎn)擊新建,new一個(gè)win32 console application工程,如下圖所示。? 名稱設(shè)為call_simple_dll。
???????????????????????????????????????????????
然后把simple_dll工程中的simple_dll.lib和simple_dll.dll拷貝到call_simple_dll工程目下文件夾下。最后在call_simple_dll下新建main.cpp文件。
2.? 調(diào)用dll中的函數(shù)
dll中的函數(shù)有兩種調(diào)用方式,靜態(tài)的和動(dòng)態(tài)的。第1節(jié)中的例子屬于靜態(tài)調(diào)用。動(dòng)態(tài)調(diào)用的方式如下:
按照第1節(jié)中的方式建立好工程,及main.cpp。具體代碼改成如下:
#include <stdio.h> #include <windows.h> typedef int(*lpAddFun)(int, int); //宏定義函數(shù)指針類型 int main(int argc, char *argv[]) {HINSTANCE hDll; //DLL 句柄lpAddFun addFun; //函數(shù)指針hDll = LoadLibrary("..\\Debug\\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; } 編譯運(yùn)行,可以得到和第1節(jié)中同樣的結(jié)果。這里我們可以看到所謂動(dòng)態(tài)調(diào)用就是使用了LoadLibrary——GetProcAddress——FreeLibrary三個(gè)windows API函數(shù)。靜態(tài)調(diào)用和動(dòng)態(tài)調(diào)用的區(qū)別在于,靜態(tài)調(diào)用需要包含lib描述文件。客戶端(即main函數(shù))編譯連接的時(shí)候,會(huì)把dll中該函數(shù)的地址綁定到main函數(shù)。這樣,一旦dll發(fā)生改變,那么函數(shù)的地址也會(huì)發(fā)生改變。客戶端也必須重新編譯連接。而動(dòng)態(tài)調(diào)用方式,因?yàn)槭褂煤笃趧?dòng)態(tài)綁定,連接的時(shí)候不需要知道函數(shù)的具體地址。只有在調(diào)用的時(shí)候,才進(jìn)行連接。這樣,無論dll中的函數(shù)怎么修改,反正在客戶端調(diào)用時(shí)會(huì)對(duì)該函數(shù)的地址進(jìn)行計(jì)算,所以即使dll發(fā)生改變,也不需要重新編譯客戶端程序。這就是動(dòng)態(tài)調(diào)用和靜態(tài)調(diào)用最主要的區(qū)別。當(dāng)然大家也可以看到,靜態(tài)調(diào)用代碼要簡(jiǎn)潔一些。所以,如果dll功能固定的話,大家可以采用靜態(tài)鏈接的方式。
3. dll中函數(shù)的導(dǎo)出
可以看到第1節(jié)中我們使用
extern "C" int _declspec(dllexport)add(int x, int y); 來聲明add函數(shù),這里_declspec(dllexport)的意思就是聲明說明(declaration spec)add函數(shù)是一個(gè)dll導(dǎo)出函數(shù)。我們可以把simple_dll.dll用vc6 tools自帶的depends工具查看,? 如下圖,我們可以看到add函數(shù)的入口指針為0x00001005 。這樣說明將add符號(hào)才可以被外界調(diào)用。?????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????????
4.dll中變量的導(dǎo)出
變量的導(dǎo)出方式跟函數(shù)基本一樣
/*文件名: variable.h */ #ifndef _VARIABLE_H_ #define _VARIABLE_H_#ifdef EXPORT #define VARIABLE_DLL _declspec(dllexport) #else #define VARIABLE_DLL _declspec(dllimport) #endif extern VARIABLE_DLL int dllglobal; #endif/*文件名:variable.cpp */ #define EXPORT #include "variable.h"int dllglobal = 33;在主函數(shù)中引用DLL 中定義的全局變量:/* 文件名:main.cpp */#include "variable.h" #include<stdio.h> #pragma comment(lib,"variable.lib")int main() {printf("%d",dllglobal); }?
注意,這里需要將variable.h,variable.lib,variable.dll都拷貝到main.cpp同個(gè)文件夾下。否則編譯不會(huì)成功。
5.dll中類的導(dǎo)出
下面的例子里,我們?cè)贒LL 中定義了point 和circle 兩個(gè)類,并在應(yīng)用工程中引用了它們。
//文件名:point.h,point 類的聲明 #ifndef POINT_H #define POINT_H#ifdef EXPORT #define CLASS_DLL _declspec(dllexport) #else #define CLASS_DLL _declspec(dllimport)#endifclass CLASS_DLL point //導(dǎo)入類point{public:float y;float x;point();point(float x_coordinate, float y_coordinate);};#endif//文件名:point.cpp,point 類的實(shí)現(xiàn) #define CLASS_DLL #include "point.h" //類point 的缺省構(gòu)造函數(shù) point::point() {x = 0.0;y = 0.0 } //類point 的構(gòu)造函數(shù) point::point(float x_coordinate, float y_coordinate) {x = x_coordinate;y = y_coordinate; }客戶端程序 #include "circle.h" //包含類聲明頭文件 #pragma comment(lib,"circle.lib"); int main() {circle c;printf("area:%f girth:%f", c.x, c.y);return 0; }
總結(jié)
以上是生活随笔為你收集整理的动态链接库的创建和调用方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 嵌入式操作系统内核原理和开发(内存分配算
- 下一篇: MCS-51单片机的指令时序