linux下檔案的類型是不依賴於其尾碼名的,但一般來講:
.o,是目標檔案,相當於windows中的.obj檔案
.so 為共用庫,是shared object,用於動態串連的,和dll差不多
.a為靜態庫,是好多個.o合在一起,用於靜態串連
.la為libtool自動產生的一些共用庫,vi編輯查看,主要記錄了一些配置資訊。可以用如下命令查看*.la檔案的格式 $file *.la
*.la: ASCII English text
動態庫*.so在linux下用c和c++編程時經常會碰到,最近在網站找了幾篇文章介紹動態庫的編譯和連結,總算搞懂了這個之前一直不太瞭解得東東,這裡做個筆記,也為其它正為動態庫連結庫而苦惱的兄弟們提供一點協助。
1、動態庫的編譯
下面通過一個例子來介紹如何產生一個動態庫。這裡有一個標頭檔:so_test.h,三個.c檔案:test_a.c、test_b.c、test_c.c,我們將這幾個檔案編譯成一個動態庫:libtest.so。
so_test.h:
#include <stdio.h>
#include <stdlib.h>
void test_a();
void test_b();
void test_c();
test_a.c:
#include "so_test.h"
void test_a()
{
printf("this is in test_a.../n");
}
test_b.c:
#include "so_test.h"
void test_b()
{
printf("this is in test_b.../n");
}
test_a.c:
#include "so_test.h"
void test_c()
{
printf("this is in test_c.../n");
}
將這幾個檔案編譯成一個動態庫:libtest.so
$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so
2、動態庫的連結
在1、中,我們已經成功產生了一個自己的動態連結程式庫libtest.so,下面我們通過一個程式來調用這個庫裡的函數。程式的源檔案為:test.c。
test.c:
#include "so_test.h"
int main()
{
test_a();
test_b();
test_c();
return 0;
}
l
將test.c與動態庫libtest.so連結產生執行檔案test:
$ gcc test.c -L. -ltest -o test
l 測試是否動態串連,如果列出libtest.so,那麼應該是串連正常了
$ ldd test
l 執行test,可以看到它是如何調用動態庫中的函數的。
3、編譯參數解析
最主要的是GCC命令列的一個選項:
-shared
該選項指定產生動態串連庫(讓連接器產生T類型的匯出符號表,有時候也產生弱串連W類型的匯出符號),不用該標誌外部程式無法串連。相當於一個可執行檔
l
-fPIC:表示編譯為位置獨立的代碼,不用此選項的話編譯後的代碼是位置相關的所以動態載入時是通過代碼拷貝的方式來滿足不同進程的需要,而不能達到真正程式碼片段共用的目的。
l
-L.:表示要串連的庫在目前的目錄中
l
-ltest:編譯器尋找動態串連庫時有隱含的命名規則,即在給出的名字前面加上lib,後面加上.so來確定庫的名稱
l
LD_LIBRARY_PATH:這個環境變數指示動態連接器可以裝載動態庫的路徑。
l
當然如果有root許可權的話,可以修改/etc/ld.so.conf檔案,然後調用
/sbin/ldconfig來達到同樣的目的,不過如果沒有root許可權,那麼只能採用輸出LD_LIBRARY_PATH的方法了。
4、注意
調用動態庫的時候有幾個問題會經常碰到,有時,明明已經將庫的標頭檔所在目錄 通過 “-I”
include進來了,庫所在檔案通過
“-L”參數引導,並指定了“-l”的庫名,但通過ldd命令察看時,就是死活找不到你指定連結的so檔案,這時你要作的就是通過修改LD_LIBRARY_PATH或者/etc/ld.so.conf檔案來指定動態庫的目錄。通常這樣做就可以解決庫無法連結的問題了。