一、靜態庫與動態庫的區別
目前以lib后綴的庫有兩種,一種為靜態鏈接庫(Static Libary,以下簡稱“靜態庫”),另一種為動態連接庫(DLL,以下簡稱“動態庫”)的導入庫(Import Libary,以下簡稱“導入庫”)。
靜態庫是一個或者多個obj文件的打包,所以有人干脆把從obj文件生成lib的過程稱為Archive,即合並到一起。比如你鏈接一個靜態庫,如果其中有錯,它會准確的找到是哪個obj有錯,即靜態lib只是殼子。
動態庫一般會有對應的導入庫,方便程序靜態載入動態鏈接庫,否則你可能就需要自己LoadLibary調入DLL文件,然后再手工GetProcAddress獲得對應函數了。有了導入庫,你只需要鏈接導入庫后按照頭文件函數接口的聲明調用函數就可以了。
導入庫和靜態庫的區別很大,他們實質是不一樣的東西。靜態庫本身就包含了實際執行代碼、符號表等等,而對於導入庫而言,其實際的執行代碼位於動態庫中,導入庫只包含了地址符號表等,確保程序找到對應函數的一些基本地址信息。
動態鏈接庫 (DLL) 是作為共享函數庫的可執行文件。動態鏈接提供了一種方法,使進程可以調用不屬於其可執行代碼的函數。函數的可執行代碼位於一個 DLL 中,該 DLL 包含一個或多個已被編譯、鏈接並與使用它們的進程分開存儲的函數。DLL 還有助於共享數據和資源。多個應用程序可同時訪問內存中單個 DLL 副本的內容。
動態鏈接與靜態鏈接的不同之處在於它允許可執行模塊(.dll 文件或 .exe 文件)僅包含在運行時定位 DLL 函數的可執行代碼所需的信息。在靜態鏈接中,鏈接器從靜態鏈接庫獲取所有被引用的函數,並將庫同代碼一起放到可執行文件中。 使用動態鏈接代替靜態鏈接有若干優點。DLL 節省內存,減少交換操作,節省磁盤空間,更易於升級,提供售后支持,提供擴展 MFC 庫類的機制,支持多語言程序,並使國際版本的創建輕松完成。
很多開源代碼發布的慣用方式:
1. 預編譯的開發包:包含一些.dll文件和一些.lib文件。其中這里的.lib就是導入庫,而不要錯以為是靜態庫。但是引入方式和靜態庫一樣,要在鏈接路徑上添加找到這些.lib的路徑。而.dll則最好放到最后產生的應用程序exe執行文件相同的目錄。這樣運行時,就會自動調入動態鏈接庫。
2. 用戶自己編譯: 下載的是源代碼,按照readme自己編譯。生成很可能也是.dll + .lib(導入庫)的庫文件
3. 如果你只有dll,並且你知道dll中函數的函數原型,那么你可以直接在自己程序中使用LoadLibary調入DLL文件,GetProcAddress
二、靜態鏈接庫
靜態鏈接庫的創建和使用都比較的簡單,我們直接看個理解就可以了。
在vs2010中新建一個Win32控制台的靜態鏈接庫工程static_lib,在工程中創建文件lib.h和lib.cpp這兩個文件,lib.h和lib.cpp的源代碼如下:
//lib.h文件 #ifndef LIB_H #define LIB_H extern "C" int add(int a, int b); //聲明為C調用方式的外部調用函數 #endif //lib.cpp文件 #include "lib.h" int add(int a, int b) { return a + b; }
直接編譯這個工程,在debug目標中就會自動生成static_lib.lib。在static_lib工程的工作區中新建libcall工程,它只有一個文件test.cpp,代碼如下:
#include "../static_lib/lib.h" #include <stdio.h> #pragma comment(lib, "..\\debug\\static_lib.lib") int main(int argc, char *argv[]) { printf("4 + 5 = %d\n", add(4, 5)); }
靜態鏈接庫的調用就是這么簡單,或許我們每天都在用,可是我們沒有明白這個概念。代碼中#pragma comment(lib, "..\\debug\\static_lib.lib")的意思是指本文件生成的.obj文件應與tatic_lib.lib一起鏈接。如果不用#pragma comment指定,則可以直接在vs中設置,如圖1,在libcall工程的屬性頁面,通過鏈接器->常規->附加庫目錄添加tatic_lib.lib所在的目錄,通過鏈接器->輸入->附加依賴項添加static_lib.lib到項目中。


圖1
直接運行就可以看到屏幕上輸出結果。
現在我們來看看static_lib.lib的反匯編結果:
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file D:\My Documents\Visual Studio 2010\Projects\static_lib\Debug\static_lib.lib File Type: LIBRARY _add: 00000000: 55 push ebp 00000001: 8B EC mov ebp,esp 00000003: 81 EC C0 00 00 00 sub esp,0C0h 00000009: 53 push ebx 0000000A: 56 push esi 0000000B: 57 push edi 0000000C: 8D BD 40 FF FF FF lea edi,[ebp+FFFFFF40h] 00000012: B9 30 00 00 00 mov ecx,30h 00000017: B8 CC CC CC CC mov eax,0CCCCCCCCh 0000001C: F3 AB rep stos dword ptr es:[edi] 0000001E: 8B 45 08 mov eax,dword ptr [ebp+8] 00000021: 03 45 0C add eax,dword ptr [ebp+0Ch] 00000024: 5F pop edi 00000025: 5E pop esi 00000026: 5B pop ebx 00000027: 8B E5 mov esp,ebp 00000029: 5D pop ebp 0000002A: C3 ret Summary 5FC .debug$S 70 .debug$T 41 .drectve 4 .rtc$IMZ 4 .rtc$TMZ 2B .text
從上面的匯編代碼可以看到static_lib.lib直接包含了add的函數代碼,這也應證了前面說的代碼直接放在靜態庫的lib文件中。
