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