庫是寫好的現有的,成熟的,可以複用的程式碼。現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的程式碼都從零開始,因此庫的存在意義非同尋常。
本質上來說庫是一種可執行程式碼的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種:靜態庫(.a、.lib)和動態庫(.so、.dll)。 windows上對應的是.lib .dll linux上對應的是.a .so
所謂靜態、動態是指連結。回顧一下,將一個程式編譯成可執行程式的步驟:
圖:編譯過程
之所以成為【靜態庫】,是因為在連結階段,會將彙編生成的目標檔案.o與引用到的庫一起連結打包到可執行檔案中。因此對應的連結方式稱為靜態連結。
試想一下,靜態庫與彙編生成的目標檔案一起連結為可執行檔案,那麼靜態庫必定跟.o檔案格式相似。其實一個靜態庫可以簡單看成是一組目標檔案(.o/.obj檔案)的集合,即很多目標檔案經過壓縮打包後形成的一個檔案。靜態庫特點總結:
l 靜態庫對函式庫的連結是放在編譯時期完成的。
l 程式在執行時與函式庫再無瓜葛,移植方便。
l 浪費空間和資源,因為所有相關的目標檔案與牽涉到的函式庫被連結合成一個可執行檔案。
Linux靜態庫命名規範,必須是"lib[your_library_name].a":lib為字首,中間是靜態庫名,副檔名為.a。
透過上面的流程可以知道,Linux建立靜態庫過程如下:
l 首先,將程式碼檔案編譯成目標檔案.o(StaticMath.o)
g++ -c StaticMath.cpp
注意帶引數-c,否則直接編譯為可執行檔案
l 然後,透過ar工具將目標檔案打包成.a靜態庫檔案
ar -crv libstaticmath.a StaticMath.o
生成靜態庫libstaticmath.a。
-------------------------------分割線------------------------
透過上面的介紹發現靜態庫,容易使用和理解,也達到了程式碼複用的目的,那為什麼還需要動態庫呢?
為什麼需要動態庫,其實也是靜態庫的特點導致。
l 空間浪費是靜態庫的一個問題。
另一個問題是靜態庫對程式的更新、部署和釋出頁會帶來麻煩。如果靜態庫liba.lib更新了,所以使用它的應用程式都需要重新編譯、釋出給使用者(對於玩家來說,可能是一個很小的改動,卻導致整個程式重新下載,全量更新)。
動態庫在程式編譯時並不會被連線到目的碼中,而是在程式執行是才被載入。不同的應用程式如果呼叫相同的庫,那麼在記憶體裡只需要有一份該共享庫的例項,規避了空間浪費問題。動態庫在程式執行是才被載入,也解決了靜態庫對程式的更新、部署和釋出頁會帶來麻煩。使用者只需要更新動態庫即可,增量更新。
動態庫特點總結:
l 動態庫把對一些庫函式的連結載入推遲到程式執行的時期。
l 可以實現程序之間的資源共享。(因此動態庫也稱為共享庫)
l 將一些程序升級變得簡單。
l 甚至可以真正做到連結載入完全由程式設計師在程式程式碼中控制(顯示呼叫)。
Window與Linux執行檔案格式不同,在建立動態庫的時候有一些差異。
l 在Windows系統下的執行檔案格式是PE格式,動態庫需要一個DllMain函式做出初始化的入口,通常在匯出函式的宣告時需要有_declspec(dllexport)關鍵字。
l Linux下gcc編譯的執行檔案預設是ELF格式,不需要初始化入口,亦不需要函式做特別的宣告,編寫比較方便。
與建立靜態庫不同的是,不需要打包工具(ar、lib.exe),直接使用編譯器即可建立動態庫。
參考於:
庫是寫好的現有的,成熟的,可以複用的程式碼。現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的程式碼都從零開始,因此庫的存在意義非同尋常。
本質上來說庫是一種可執行程式碼的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種:靜態庫(.a、.lib)和動態庫(.so、.dll)。 windows上對應的是.lib .dll linux上對應的是.a .so
在這裡先介紹下Linux下的gcc編譯的幾個選項會將hellospeak.cpp 選項 -c 用來告訴編譯器編譯原始碼但不要執行連結,輸出結果為物件檔案。檔案預設名與原始碼檔名相同,只是將其後綴變為 .o。例如,上面的命令將編譯原始碼檔案hellospeak.cpp 並生成物件檔案 hellospeak.o;下面這條命令將上述兩個原始碼檔案編譯連結成一個單一的可執行程式: 如果沒有-o和後面的引數,編譯器採用預設的 a.out本例中就會生成hellospeak 這樣的可執行程式所謂靜態、動態是指連結。回顧一下,將一個程式編譯成可執行程式的步驟:
圖:編譯過程
靜態庫之所以成為【靜態庫】,是因為在連結階段,會將彙編生成的目標檔案.o與引用到的庫一起連結打包到可執行檔案中。因此對應的連結方式稱為靜態連結。
試想一下,靜態庫與彙編生成的目標檔案一起連結為可執行檔案,那麼靜態庫必定跟.o檔案格式相似。其實一個靜態庫可以簡單看成是一組目標檔案(.o/.obj檔案)的集合,即很多目標檔案經過壓縮打包後形成的一個檔案。靜態庫特點總結:
l 靜態庫對函式庫的連結是放在編譯時期完成的。
l 程式在執行時與函式庫再無瓜葛,移植方便。
l 浪費空間和資源,因為所有相關的目標檔案與牽涉到的函式庫被連結合成一個可執行檔案。
Linux下建立與使用靜態庫Linux靜態庫命名規則Linux靜態庫命名規範,必須是"lib[your_library_name].a":lib為字首,中間是靜態庫名,副檔名為.a。
建立靜態庫(.a)透過上面的流程可以知道,Linux建立靜態庫過程如下:
l 首先,將程式碼檔案編譯成目標檔案.o(StaticMath.o)
g++ -c StaticMath.cpp
注意帶引數-c,否則直接編譯為可執行檔案
l 然後,透過ar工具將目標檔案打包成.a靜態庫檔案
ar -crv libstaticmath.a StaticMath.o
生成靜態庫libstaticmath.a。
-------------------------------分割線------------------------
動態庫透過上面的介紹發現靜態庫,容易使用和理解,也達到了程式碼複用的目的,那為什麼還需要動態庫呢?
為什麼還需要動態庫?為什麼需要動態庫,其實也是靜態庫的特點導致。
l 空間浪費是靜態庫的一個問題。
另一個問題是靜態庫對程式的更新、部署和釋出頁會帶來麻煩。如果靜態庫liba.lib更新了,所以使用它的應用程式都需要重新編譯、釋出給使用者(對於玩家來說,可能是一個很小的改動,卻導致整個程式重新下載,全量更新)。
動態庫在程式編譯時並不會被連線到目的碼中,而是在程式執行是才被載入。不同的應用程式如果呼叫相同的庫,那麼在記憶體裡只需要有一份該共享庫的例項,規避了空間浪費問題。動態庫在程式執行是才被載入,也解決了靜態庫對程式的更新、部署和釋出頁會帶來麻煩。使用者只需要更新動態庫即可,增量更新。
動態庫特點總結:
l 動態庫把對一些庫函式的連結載入推遲到程式執行的時期。
l 可以實現程序之間的資源共享。(因此動態庫也稱為共享庫)
l 將一些程序升級變得簡單。
l 甚至可以真正做到連結載入完全由程式設計師在程式程式碼中控制(顯示呼叫)。
Window與Linux執行檔案格式不同,在建立動態庫的時候有一些差異。
l 在Windows系統下的執行檔案格式是PE格式,動態庫需要一個DllMain函式做出初始化的入口,通常在匯出函式的宣告時需要有_declspec(dllexport)關鍵字。
l Linux下gcc編譯的執行檔案預設是ELF格式,不需要初始化入口,亦不需要函式做特別的宣告,編寫比較方便。
與建立靜態庫不同的是,不需要打包工具(ar、lib.exe),直接使用編譯器即可建立動態庫。
參考於: