天天看點

靜态連結庫和動态連結庫

靜态連結庫

windows下的靜态連結庫

靜态連結庫就是你使用的.lib檔案,庫中的代碼最後需要連接配接到你的可執行檔案中去,是以靜态連接配接的可執行檔案一般比較大一些。

引用:

一、通用:

格式如:#pragma comment(lib,"XXX.lib")

二、針對開發環境:

1、如果使用VC,可以在Project Setting-->Link中加入你的靜态庫,也可以直接把該.lib檔案加入到你的工程中

2、如果使用Visual Studio,位置在 項目→配置屬性→連接配接器→輸入→附加依賴項 中加入.lib檔案

靜态連結庫不同于動态連結庫(*.dll),在靜态庫情況下,函數和資料被編譯進一個二進制檔案(通常擴充名為*.LIB),Visual C++的編譯器在連結過程中将從靜态庫中恢複這些函數和資料并把他們和應用程式中的其他子產品組合在一起生成可執行檔案。這個過程稱為"靜态連結",此時因為應用程式所需的全部内容都是從庫中複制了出來,是以靜态庫本身并不需要與可執行檔案一起發行。

linux下的靜态連結庫

linux下的靜态連結庫是*.a檔案,與動态連結庫.so對應。*.a檔案是由單個或多個.o檔案組成的

類似的.lib檔案是由單個或多個.obj檔案組成的

linux下.a檔案,如果編寫了入口函數,也可以直接執行

靜态連結庫與動态連結庫(上)

一、分别編譯與連結(Linking)

大多數進階語言都支援分别編譯,程式員可以顯式地把程式劃分為獨立的子產品或檔案,然後每個獨立部分分别編譯。在編譯之後,由連結器把這些獨立的片段(稱為編譯單元)“粘接到一起”。(想想這樣做有什麼好處?)

在C/C++中,這些獨立的編譯單元包括obj檔案(一般的源程式編譯而成)、lib檔案(靜态連結的函數庫)、dll檔案(動态連結的函數庫)等。

靜态連結方式:在程式執行之前完成所有的組裝工作,生成一個可執行的目标檔案(EXE檔案)。

動态連結方式:在程式已經為了執行被裝入記憶體之後完成連結工作,并且在記憶體中一般隻保留該編譯單元的一份拷貝。

二、靜态連結庫與動态連結庫

先來闡述一下DLL(Dynamic Linkable Library)的概念,你可以簡單的把DLL看成一種倉庫,它提供給你一些可以直接拿來用的變量、函數或類。

靜态連結庫與動态連結庫都是共享代碼的方式,如果采用靜态連結庫,則無論你願不願意,lib中的指令都被直接包含在最終生成的EXE檔案中了。但是若使用DLL,該DLL不必被包含在最終的EXE檔案中,EXE檔案執行時可以“動态”地引用和解除安裝這個與EXE獨立的DLL檔案。

采用動态連結庫的優點:(1)更加節省記憶體;(2)DLL檔案與EXE檔案獨立,隻要輸出接口不變,更換DLL檔案不會對EXE檔案造成任何影響,因而極大地提高了可維護性和可擴充性。

三、靜态連結庫的制作

對靜态連結庫的講解不是本文的重點,但是在具體講解DLL之前,通過一個靜态連結庫的例子可以快速地幫助我們建立“庫”的概念。

靜态連結庫和動态連結庫

圖1 建立一個靜态連結庫

如圖1,在VC++6.0中new一個名稱為libTest的static library工程,并建立lib.h和lib.cpp兩個檔案,lib.h和lib.cpp的源代碼如下:

//檔案:lib.h

#ifndef LIB_H

#define LIB_H

extern "C" int add(int x,int y);   //聲明為C編譯、連接配接方式的外部函數

#endif

//檔案:lib.cpp

#include "lib.h"

int add(int x,int y)

{

return x + y;

}

編譯這個工程就得到了一個libTest.lib檔案,這個檔案就是一個函數庫,它提供了add的功能。将頭檔案lib.h和libTest.lib檔案送出給使用者後,使用者就可以直接使用其中的add函數了。常用的标準C庫函數(scanf、printf、memcpy、strcpy等)就來自這種靜态庫。

四、靜态連結庫的調用

下面來看看怎麼使用這個庫。在VC中new一個名為libCall的Win32 Console Application工程,并将上面生成的檔案lib.h和libTest.lib檔案拷貝到libCall的工程子目錄下。libCall工程僅包含一個main.cpp檔案,它示範了靜态連結庫的調用方法,其源代碼如下:

#include <stdio.h>

#pragma comment( lib, "libTest.lib" )   //指定與靜态庫一起連接配接

int main()

printf( "2 + 3 = %d", add( 2, 3 ) );

靜态連結庫的調用就是這麼簡單,或許我們每天都在用,可是我們沒有明白這個概念。代碼中#pragma comment( lib , "libTest.lib" )的意思是指本檔案生成的.obj檔案應與libTest.lib一起連接配接。

如果不用#pragma comment指定,則可以直接在VC++中設定,如圖2,依次選擇tools、options、directories、library files菜單或選項,填入庫檔案路徑。圖2中加圈的部分為我們添加的libTest.lib檔案的路徑。

靜态連結庫和動态連結庫

圖2 在VC中設定庫檔案路徑

這個靜态連結庫的例子至少讓我們明白了庫函數是怎麼回事,它們是哪來的。我們現在有下列模糊認識了:

(1)庫不是個怪物,編寫庫的程式和編寫一般的程式差別不大,隻是庫不能單獨執行;

(2)庫提供一些可以給别的程式調用的東東,别的程式要調用它必須以某種方式指明它要調用之。

以上從靜态連結庫分析而得到的對庫的懵懂概念可以直接引申到動态連結庫中,動态連結庫與靜态連結庫在編寫和調用上的不同展現在庫的外部接口定義及調用方式略有差異。

---------------------------------------------------------------------------------------------------

以下為接靜态連結庫與動态連結庫(下)未完部分:

九、動态連結庫的應用舉例

1、所有的Windows系統調用(Windows API函數)都是以動态連結庫的形式提供的。我們在Windows目錄下的system32檔案夾中會看到kernel32.dll、user32.dll和gdi32.dll,windows的大多數API都包含在這些DLL中。kernel32.dll中的函數主要處理記憶體管理和程序排程;user32.dll中的函數主要控制使用者界面;gdi32.dll中的函數則負責圖形方面的操作。與這些動态庫相對應的導入庫分别為kernel32.lib、user32.lib和gdi32.lib。

2、軟體的自動更新。Windows應用的開發者常常利用動态連結庫來分發軟體更新。他們生成一個動态庫的新版本,然後使用者可以下載下傳,并用它替代目前的版本。當然,新、舊版本動态庫的輸出接口(即導出函數)必須一緻。下一次使用者運作應用程式時,應用将自動連結和加載新的動态庫。

繼續閱讀