日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态链接库编程

發(fā)布時間:2024/4/11 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态链接库编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Windows 動態(tài)鏈接庫編程 ?

1、介紹

Windows操作系統(tǒng)是應用最關的操作系統(tǒng),因此動態(tài)鏈接庫也為程序員所熟悉,即使對于普通的使用者來說,很多時候也會碰到.dll結尾的文件,這就是動態(tài)鏈接庫文件。Windows下的動態(tài)鏈接庫可以通過參考頭文件和.lib庫文件進行編譯,從而使得動態(tài)鏈接庫隱式地被使用;也可以使用LoadLibrary、GetProcAddress等函數來顯式調用動態(tài)鏈接庫。

2、語法、導入導出

在Windows編程中,對于要使用或被使用的函數或者變量,需要使用 __declspec 關鍵字來聲明,以告訴編譯器該變量或函數不是普通的變量或函數,而是一個動態(tài)鏈接庫的接口屬性。

如果定義一個要被其他代碼使用的函數,可以寫成:
__declspec( dllexport ) int add(int a, int b);

如果在該代碼中,打算使用另外一個程序中的變量,則可以寫成:
__declspec( dllimport ) char *name;

動態(tài)鏈接庫通常包含一系列供其他程序使用函數,因此 declspec( dllexport ) 語法形式最為常用。如果動態(tài)庫需要其他程序中的定義的全局變量,則需要在其他程序中使用導出該變量,在動態(tài)鏈接庫中則需要使用 extern declspec( dllexport ) 將該變量聲明為外部變量以便使用。

3、鏈接方式

可以以下列兩種方式之一鏈接到(或加載)DLL:

隱式鏈接
顯式鏈接

隱式鏈接有時稱為靜態(tài)加載或加載時動態(tài)鏈接。顯式鏈接有時稱為動態(tài)加載或運行時動態(tài)鏈接。在隱式鏈接下,使用 DLL 的可執(zhí)行文件鏈接到該 DLL 的創(chuàng)建者所提供的導入庫(.lib 文件)。使用 DLL 的可執(zhí)行文件加載時,操作系統(tǒng)加載此 DLL。客戶端可執(zhí)行文件調用 DLL 的導出函數,就好像這些函數包含在可執(zhí)行文件內一樣。

在顯式鏈接下,使用 DLL 的可執(zhí)行文件必須進行函數調用以顯式加載和卸載該 DLL,并訪問該 DLL 的導出函數。客戶端可執(zhí)行文件必須通過函數指針調用導出函數。可執(zhí)行文件對兩種鏈接方法可以使用同一個 DLL。另外,由于一個可執(zhí)行文件可隱式鏈接到某個 DLL,而另一個可顯式附加到此 DLL,故這些機制不是互斥的。

4、隱式鏈接

隱式鏈接動態(tài)鏈接庫比較簡單,不予詳述。

5、顯式鏈接API函數

顯式鏈接主要涉及到3個API函數( LoadLibrary , GetProcAddress 和 FreeLibrary ),要使用這些函數包含windows.h頭文件即可。

(1)HINSTANCE LoadLibrary(LPCSTR lpLibFileName);

該函數用來加載指定動態(tài)庫文件,并且返回句柄。

參數lpLibFileName為動態(tài)鏈接庫的名稱。Windows 首先搜索“已知 DLL”,如 Kernel32.dll 和 User32.dll。然后按下列順序搜索 DLL:

1、當前進程的可執(zhí)行模塊所在的目錄。
2、當前目錄。
3、Windows 系統(tǒng)目錄。GetSystemDirectory 函數檢索此目錄的路徑。
4、Windows 目錄。GetWindowsDirectory 函數檢索此目錄的路徑。
5、PATH 環(huán)境變量中列出的目錄。

(2)FARPROC GetProcAddress (HMODULE hModule, LPCSTR lpProcName);

函數GetProcAddress 用來獲取 DLL 導出函數的地址。返回由lpProcName指定的變量或函數指針。

參數hModule為已經加載的動態(tài)庫文件的句柄。

參數lpProcName為要調用的變量或函數名稱。

(3)BOOL FreeLibrary(HMODULE hModule);
從內存中釋放hModule所代表的動態(tài)鏈接庫。

(4)如果發(fā)生錯誤,可以調用GetLastError()函數或去錯誤代碼。

6、顯示鏈接舉例

(1)動態(tài)庫文件代碼:dll_demo.c

#include <stdio.h>

__declspec( dllexport ) int add(int a, int b)
{
printf("calling add\n");
return a + b;
}

該文件中的add()函數計算兩個整數之和,并且返回之前打印提示字符串。函數使用 __declspec( dllexport ) 語法來說明函數add(int a, int b)要被導出。

(2)客戶端事例代碼:main.c

#include <stdio.h>
#include <windows.h>

int main (int argc, char *argv[])
{
int a = 10, b = 20;
int c = 0;
HINSTANCE?? hInstLibrary?? =?? NULL;
int (*add)();

printf ("Load DLL file\n");
if ((hInstLibrary = LoadLibrary(L"dll_demo.dll")) == NULL)
{
?? printf ("***LoadLibrary ERROR: %d.\n", GetLastError());
?? return 1;
}
if((add = (int (*)())GetProcAddress(hInstLibrary, "add")) == NULL) {
?? printf ("***GetProcAddress ERROR: %d.\n", GetLastError());
?? return 1;
}

c = add(a, b);
printf("%d + %d = %d\n", a, b, c);

FreeLibrary(hInstLibrary);
return 0;
}

程序利用LoadLibrary函數加載動態(tài)鏈接dll_demo.dll,利用FreeLibrary關閉句柄,利用GetLastError()獲取錯誤代碼,利用GetProcAddress定位共享庫中的add函數,然后調用該函數執(zhí)行加法計算,并打印結果。

(3)編譯與運行

編譯共享庫:

在VS.Net中創(chuàng)建一個動態(tài)鏈接庫項目,名稱為dll_demo,加入文件dll_demo.c,編譯后生成dll_demo.dll文件。

編譯事例程序:

在VS.Net中創(chuàng)建一個動態(tài)鏈接庫項目,名稱為dll_main,加入文件main.c,編譯后生成dll_main.exe可以執(zhí)行文件。

運行:

將 dll_demo.dll 和 dll_main.exe 放在同一個目錄下,然后雙擊運行 dll_main.exe。

輸出:

Load DLL file
calling add
10 + 20 = 30

7、調用動態(tài)鏈接庫中的變量

也可以使用動態(tài)鏈接庫中的變量。例如,在動態(tài)鏈接庫中定義:

__declspec( dllexport ) int num = 100;

那么可以在事例程序中這樣調用:

int *d;
d = (int *)GetProcAddress(hInstLibrary, "num");
printf("num = %d\n", *d);

總結

以上是生活随笔為你收集整理的动态链接库编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。