1. 程式人生 > >C++靜態庫與動態庫、建立及呼叫方法

C++靜態庫與動態庫、建立及呼叫方法

1 什麼是庫

庫是寫好的現有的,成熟的,可以複用的程式碼。現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的程式碼都從零開始,因此庫的存在意義非同尋常。本質上來說庫是一種可執行程式碼的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種:靜態庫(.a、.lib)和動態庫(.so、.dll)。所謂靜態、動態是指連結。回顧一下,將一個程式編譯成可執行程式的步驟:


圖1:編譯過程

1.1 靜態庫

之所以成為【靜態庫】,是因為在連結階段,會將彙編生成的目標檔案.o與引用到的庫一起連結打包到可執行檔案中。因此對應的連結方式稱為靜態連結。試想一下,靜態庫與彙編生成的目標檔案一起連結為可執行檔案,那麼靜態庫必定跟.o檔案格式相似。其實一個靜態庫簡單可以看成是一組目標檔案(.o/.obj檔案)的集合,即很多目標檔案經過壓縮打包後形成的一個檔案。靜態庫特點總結:

l  靜態庫對函式庫的連結是放在編譯時期完成的。
l  程式在執行時與函式庫再無瓜葛,移植方便。
l  浪費空間和資源,因為所有相關的目標檔案與牽涉到的函式庫被連結合成一個可執行檔案。
下面編寫一些簡單的四則運算C++類,將其編譯成靜態庫給他人用,標頭檔案(StaticMath.h標頭檔案)如下所示:

#pragma once
class StaticMath
{
public:
    StaticMath(void);
    ~StaticMath(void);
 
    static double add(double a, double b);//加法
    static double sub(double a, double b);//減法
    static double mul(double a, double b);//乘法
    static double div(double a, double b);//除法
 
    void print();
};
Linux下使用ar工具、Windows下vs使用lib.exe,將目標檔案壓縮到一起,並且對其進行編號和索引,以便於查詢和檢索。一般建立靜態庫的步驟如圖所示:

圖2:建立靜態庫過程


2 Linux下建立與使用靜態庫

2.1 Linux靜態庫命名規則

Linux靜態庫命名規範,必須是"lib[your_library_name].a":lib為字首,中間是靜態庫名,副檔名為.a。

2.2 建立靜態庫(.a)

通過上面的流程可以知道,Linux建立靜態庫過程如下:

l  首先,將程式碼檔案編譯成目標檔案.o(StaticMath.o)
g++ -c StaticMath.cpp
注意帶引數-c,否則直接編譯為可執行檔案
l  然後,通過ar工具將目標檔案打包成.a靜態庫檔案
ar -crv libstaticmath.a StaticMath.o
生成靜態庫libstaticmath.a。


大一點的專案會編寫makefile檔案(CMake等等工程管理工具)來生成靜態庫,輸入多個命令太麻煩了。

2.3 使用靜態庫

編寫使用上面建立的靜態庫的測試程式碼:

#include "StaticMath.h"
#include <iostream>
using namespace std;
 
int main(int argc, char* argv[])
{
    double a = 10;
    double b = 2;
 
    cout << "a + b = " << StaticMath::add(a, b) << endl;
    cout << "a - b = " << StaticMath::sub(a, b) << endl;
    cout << "a * b = " << StaticMath::mul(a, b) << endl;
    cout << "a / b = " << StaticMath::div(a, b) << endl;
 
    StaticMath sm;
    sm.print();
 
    system("pause");
    return 0;
}
Linux下使用靜態庫,只需要在編譯的時候,指定靜態庫的搜尋路徑(-L選項)、指定靜態庫名(不需要lib字首和.a字尾,-l選項)。
# g++ TestStaticLibrary.cpp -L../StaticLibrary -lstaticmath


l  -L:表示要連線的庫所在目錄
l  -l:指定連結時需要的動態庫,編譯器查詢動態連線庫時有隱含的命名規則,即在給出的名字前面加上lib,後面加上.a或.so來確定庫的名稱。

3 Windows下建立與使用靜態庫

3.1 建立靜態庫(.lib)

如果是使用VS命令列生成靜態庫,也是分兩個步驟來生成程式:
l  首先,通過使用帶編譯器選項 /c 的 Cl.exe 編譯程式碼 (cl /c StaticMath.cpp),建立名為“StaticMath.obj”的目標檔案。
l  然後,使用庫管理器 Lib.exe 連結程式碼 (lib StaticMath.obj),建立靜態庫StaticMath.lib。
當然,我們一般不這麼用,使用VS工程設定更方便。建立win32控制檯程式時,勾選靜態庫型別;開啟工程“屬性面板”è”配置屬性”è”常規”,配置型別選擇靜態庫。


圖:vs靜態庫專案屬性設定

Build專案即可生成靜態庫。

3.2 使用靜態庫
測試程式碼Linux下面的一樣。有3種使用方法:

方法一:

在VS中使用靜態庫方法:
l  工程“屬性面板”è“通用屬性”è “框架和引用”è”新增引用”,將顯示“新增引用”對話方塊。 “專案”選項卡列出了當前解決方案中的各個專案以及可以引用的所有庫。 在“專案”選項卡中,選擇 StaticLibrary。 單擊“確定”。


l  新增StaticMath.h 標頭檔案目錄,必須修改包含目錄路徑。開啟工程“屬性面板”——》”配置屬性”——》“C/C++”——》” 常規”,在“附加包含目錄”屬性值中,鍵入StaticMath.h 標頭檔案所在目錄的路徑或瀏覽至該目錄。


編譯執行OK。

如果引用的靜態庫不是在同一解決方案下的子工程,而是使用第三方提供的靜態庫lib和標頭檔案,上面的方法設定不了。還有2中方法設定都可行。

方法二:
開啟工程“屬性面板”——》”配置屬性”——》 “連結器”——》”命令列”,輸入靜態庫的完整路徑即可。

方法三:
l  “屬性面板”——》”配置屬性”——》“連結器”——》”常規”,附加依賴庫目錄中輸入,靜態庫所在目錄;
l  “屬性面板”——》”配置屬性”——》“連結器”——》”輸入”,附加依賴庫中輸入靜態庫名StaticLibrary.lib。

出處:http://www.cnblogs.com/skynet/