歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C++靜態庫與動態庫

這次分享的宗旨是——讓大家學會創建與使用靜態庫、動態庫,知道靜態庫與動態庫的區別,知道使用的時候如何選擇。這裡不深入介紹靜態庫、動態庫的底層格式,內存布局等,有興趣的同學,推薦一本書《程序員的自我修養——鏈接、裝載與庫》。

《程序員的自我修養——鏈接、裝載與庫》掃描版PDF下載  http://www.linuxidc.com/Linux/2011-09/43809.htm

什麼是庫

庫是寫好的現有的,成熟的,可以復用的代碼。現實中每個程序都要依賴很多基礎的底層庫,不可能每個人的代碼都從零開始,因此庫的存在意義非同尋常

本質上來說庫是一種可執行代碼的二進制形式,可以被操作系統載入內存執行。庫有兩種:靜態庫(.a、.lib)和動態庫(.so、.dll)。

所謂靜態、動態是指鏈接。回顧一下,將一個程序編譯成可執行程序的步驟:

圖:編譯過程

靜態庫

之所以成為【靜態庫】,是因為在鏈接階段,會將匯編生成的目標文件.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,將目標文件壓縮到一起,並且對其進行編號和索引,以便於查找和檢索。一般創建靜態庫的步驟如圖所示:

圖:創建靜態庫過程

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

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

使用靜態庫

編寫使用上面創建的靜態庫的測試代碼:

測試代碼:

#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來確定庫的名稱。

 

Windows下創建與使用靜態庫

創建靜態庫(.lib)

如果是使用VS命令行生成靜態庫,也是分兩個步驟來生成程序:

l  首先,通過使用帶編譯器選項 /c 的 Cl.exe 編譯代碼 (cl /c StaticMath.cpp),創建名為“StaticMath.obj”的目標文件。

l  然後,使用庫管理器 Lib.exe 鏈接代碼 (lib StaticMath.obj),創建靜態庫StaticMath.lib。

當然,我們一般不這麼用,使用VS工程設置更方便。創建win32控制台程序時,勾選靜態庫類型;打開工程“屬性面板”è”配置屬性”è”常規”,配置類型選擇靜態庫。

圖:vs靜態庫項目屬性設置

Build項目即可生成靜態庫。

使用靜態庫

測試代碼Linux下面的一樣。有3種使用方法:

方法一:

在VS中使用靜態庫方法:

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

l  添加StaticMath.h 頭文件目錄,必須修改包含目錄路徑。打開工程“屬性面板”è”配置屬性”è “C/C++”è”常規”,在“附加包含目錄”屬性值中,鍵入StaticMath.h 頭文件所在目錄的路徑或浏覽至該目錄。

編譯運行OK。

圖:靜態庫測試結果(vs)

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

方法二:

打開工程“屬性面板”è”配置屬性”è “鏈接器”è”命令行”,輸入靜態庫的完整路徑即可。

方法三:

l  “屬性面板”è”配置屬性”è “鏈接器”è”常規”,附加依賴庫目錄中輸入,靜態庫所在目錄;

l  “屬性面板”è”配置屬性”è “鏈接器”è”輸入”,附加依賴庫中輸入靜態庫名StaticLibrary.lib。

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2015-04/115811p2.htm

Copyright © Linux教程網 All Rights Reserved