1. 程式人生 > 其它 >GCC靜態庫、動態庫探幽

GCC靜態庫、動態庫探幽

任務目標用 gcc 生成 .a 靜態庫和 .so 動態庫

使用環境:Linux

Step1:編輯生成例子程式 hello.h、hello.c 和 main.c

  首先編輯hello.h檔案內容

  

  hello.c

  

  main.c
  

  樣例的三個程式碼如下:

  

程式 1: hello.h
ifndef HELLO_H
define HELLO_H
void hello(const char *name);
endif //HELLO_H

程式 2: hello.c
#include <stdio.h>
void hello(const char
*name) { printf("Hello %s!\n", name); } 程式 3: main.c #include "hello.h" int main() { hello("everyone"); return 0; }

如上 我們就完成了第一步工作。

Step2:第 2 步:將 hello.c 編譯成.o 檔案

  無論靜態庫,還是動態庫,都是由.o 檔案建立的。因此,我們必須將源程式 hello.c 通過 g cc 先編譯成.o 檔案。在系統提示符下鍵入以下命令得到 hello.o 檔案。

  

  在 ls 命令結果中,我們看到了 hello.o 檔案,本步操作完成。 下面我們先來看看如何建立靜態庫,以及使用它。

Step3:由.o 檔案建立靜態庫
  
靜態庫檔名的命名規範是以 lib 為字首,緊接著跟靜態庫名,副檔名為.a。例如:我們將 建立的靜態庫名為 myhello,則靜態庫檔名就是 libmyhello.a。在建立和使用靜態庫時, 需要注意這點。建立靜態庫用 ar 命令。在系統提示符下鍵入以下命令將建立靜態庫檔案 libmyhello.a。

Step4:靜態庫在程式中使用

  提供了三種可以參考的方法,文章中實際操作才用了第二種

靜態庫製作完了,如何使用它內部的函式呢?只需要在使用到這些公用函式的源程式中包
含這些公用函式的原型宣告,然後在用 gcc 命令生成目標檔案時指明靜態庫名,gcc 將會從
靜態庫中將公用函式連線到目標檔案中。注意,gcc 會在靜態庫名前加上字首 lib,然後追
加副檔名.a 得到的靜態庫檔名來查詢靜態庫檔案。
在程式 
3:main.c 中,我們包含了靜態庫的標頭檔案 hello.h,然後在主程式 main 中直接呼叫 公用函式 hello。下面先生成目標程式 hello,然後執行 hello 程式看看結果如何。
方法一: # gcc
-o hello main.c -L. –lmyhello 自定義的庫時,main.c 還可放在-L.和 –lmyhello 之間,但是不能放在它倆之後,否則會提 示 myhello 沒定義,但是是系統的庫時,如 g++ -o main(-L/usr/lib) -lpthread main.cpp 就不出錯。
方法二: #gcc main.c libmyhello.a
-o hello
方法三: 先生成 main.o: gcc
-c main.c 再生成可執行檔案: gcc -o hello main.o libmyhello.a 動態庫連線時也可以這樣做。 # ./hello Hello everyone!

我們刪除靜態庫檔案試試公用函式 hello 是否真的連線到目標檔案 hello 中了。 # rm libmyhello.a rm: remove regular file `libmyhello.a'? y # ./hello Hello everyone! # 程式照常執行,靜態庫中的公用函式已經連線到目標檔案中了。 我們繼續看看如何在 Linux 中建立動態庫。我們還是從.o 檔案開始。

程式照常執行,靜態庫中的公用函式已經連線到目標檔案中了。

接下來我們繼續看看如何在 Linux 中建立動態庫。我們還是從.o 檔案開始

Step5:由.o 檔案建立動態庫檔案

  動態庫檔名命名規範和靜態庫檔名命名規範類似,也是在動態庫名增加字首 lib,但其 副檔名為.so。例如:我們將建立的動態庫名為 myhello,則動態庫檔名就是 libmyh ello.so。用 gcc 來建立動態庫。 在系統提示符下鍵入以下命令得到動態庫檔案 libmyhello.so。

輸入以下命令 生成.so檔案 同時利用ls檢視是否生成

Step6:在程式中使用動態庫

  在程式中使用動態庫和使用靜態庫完全一樣,也是在使用到這些公用函式的源程式中包含 這些公用函式的原型宣告,然後在用 gcc 命令生成目標檔案時指明動態庫名進行編譯。我 們先執行 gcc 命令生成目標檔案,再執行它看看結果。

  warning:#gcc main.c libmyhello.so -o hello 不會出錯(沒有 libmyhello.so 的話,會出錯),但是 接下來./hello 會提示出錯,因為雖然連線時用的是當前目錄的動態庫,但是執行時,是到 /usr/lib 中找庫檔案的,將檔案 libmyhello.so 複製到目錄/usr/lib 中

  

  

成功執行!

Step end:一探究竟

  上述步驟進一步說明了動態庫在程式執行時是需要的。 我們回過頭看看,發現使用靜態庫和使用動態庫編譯成目標程式使用的 gcc 命令完全一樣, 那當靜態庫和動態庫同名時,gcc 命令會使用哪個庫檔案呢?抱著對問題必究到底的心情, 來試試看。 先刪除除.c 和.h 外的所有檔案,恢復成我們剛剛編輯完舉例程式狀態。

再來建立靜態庫檔案 libmyhello.a 和動態庫檔案 libmyhello.so

通過上述最後一條 ls 命令,可以發現靜態庫檔案 libmyhello.a 和動態庫檔案 libmyhello.s o 都已經生成,並都在當前目錄中。然後,我們執行 gcc 命令來使用函式庫 myhello 生成目 標檔案 hello,並執行程式 hello。

# gcc -o hello main.c -L. –lmyhello
(動態庫和靜態庫同時存在時,優先使用動態庫,當然,如果直接
#gcc main.c libmyhello.a -o hello 的話,就是指定為靜態庫了)
# ./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shar
ed object file: No such file or directory
#
從程式 hello 執行的結果中很容易知道,當靜態庫和動態庫同名時,gcc 命令將優先使用動
態庫,預設去連/usr/lib 和/lib 等目錄中的動態庫,將檔案 libmyhello.so 複製到目錄/usr/lib
中即可。

實驗心得:本次實驗更加深入的瞭解和體會了GCC的使用過程,已經瞭解鞏固了Linux的一些檔案的命令,在實驗過程中雖然曲折,遇到了一些問題,但是通過文件和Google的方式得以解決,在其中體會到了許多樂趣,以及更加進一步的瞭解動態庫和靜態庫的不同區別,感覺對於GCC的瞭解加深了一些,同時更加喜歡了Linux下的操作方式,很有收穫