【C++從入門到放棄】C++編譯生成動態鏈接庫*.so及如何調用*.so

動態庫*.so在linux下用c和c++編程時經常會碰到,最近在網站找了幾篇文章介紹動態庫的編譯和鏈接,總算搞懂了這個之前一直不太瞭解得東東,這裏做個筆記,
也爲其它正爲動態庫鏈接庫而苦惱的兄弟們提供一點幫助。

談點實際價值:
如果個人是使用的是Mac,而別人提供的鏈接庫文件*.so是linux的,那麼這個時候就不能直接使用了,這個鏈接表源文件在的話可以按照如下教程自行進行生成Mac版的

動態庫的編譯

下面通過一個例子來介紹如何生成一個動態庫。這裏有一個頭文件:so_test.h,三個.c文件:test_a.c、test_b.c、test_c.c,
我們將這幾個文件編譯成一個動態庫:libtest.so

$ more so_test.h 
#ifndef CSTUDTY5_SO_TEST_H
#define CSTUDTY5_SO_TEST_H

#include "stdio.h"

void test_a();

void test_b();

void test_c();

#endif //CSTUDTY5_SO_TEST_H

$ more test_a.c 
#include "so_test.h"

void test_a() {
    printf("this is in test_a...\n");
}

$ more test_b.c 
#include "so_test.h"
void test_b()
{
    printf("this is in test_b...\n");
}

$ more test_c.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
或者
$ g++ test_a.c test_b.c test_c.c -fPIC -shared -o libtest2.so

上述2個命令選擇其中1個就成,可以爬到通過gcc與g++生成的動態庫文件大小略有區別的


$ ll
drwxr-xr-x  10 mac  staff   320 Jun  4 19:32 .
drwxr-xr-x   9 mac  staff   288 Jun  4 19:32 ..
-rwxr-xr-x   1 mac  staff  8440 Jun  4 19:32 libtest.so
-rwxr-xr-x   1 mac  staff  8456 Jun  4 19:32 libtest2.so
-rw-r--r--   1 mac  staff   151 Jun  4 19:28 so_test.h
-rw-r--r--   1 mac  staff    78 Jun  4 18:57 test_a.c
-rw-r--r--   1 mac  staff    77 Jun  4 18:58 test_b.c
-rw-r--r--   1 mac  staff    77 Jun  4 19:30 test_c.c

動態庫的鏈接/動態庫的使用

我們已經成功生成了一個自己的動態鏈接庫libtest.so,下面我們通過一個程序來調用這個庫裏的函數。程序的源文件爲:test.c。

$ more test.c
#include "so_test.h"

int main() {
    test_a();
    test_b();
    test_c();
    return 0;
}

將test.c與動態庫libtest.so鏈接生成執行文件test:

$ gcc test.c -L. -ltest -o test
或者
$ g++ test.c -L. -ltest2 -o test2

到此爲止,已經生成了可執行文件test,test2,可以執行命令看看(執行成功,完美)

$ ./test
this is in test_a...
this is in test_b...
this is in test_c...

$ ./test2
this is in test_a...
this is in test_b...
this is in test_c...

擴展練習

我們修改下test_c.c文件

$ more test_c.c
   #include "so_test.h"

   void test_c() {
       printf("this is in test_cccccc...\n");
   }

重新生成下相應的動態庫libtest.so

$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so

再執行下之前生成的可執行程序test(注意:這裏可沒有重新生成可執行程序test喲)

$ ./test
this is in test_a...
this is in test_b...
this is in test_cccccc...

題外話:動態鏈接庫的意思就是鏈接庫獨立存在,變更之後,之前依賴它的可執行程序會自動使用新的鏈接庫進行執行。

編譯參數解析

最主要的是GCC命令行的一個選項:

  • -shared該選項指定生成動態連接庫(讓連接器生成T類型的導出符號表,有時候也生成弱連接W類型的導出符號),不用該標誌外部程序無法連接。相當於一個可執行文件

  • -fPIC:表示編譯爲位置獨立的代碼,不用此選項的話編譯後的代碼是位置相關的所以動態載入時是通過代碼拷貝的方式來滿足不同進程的需要,而不能達到真正代碼段共享的目的。

  • -L.:表示要連接的庫在當前目錄中

  • -ltest:編譯器查找動態連接庫時有隱含的命名規則,即在給出的名字前面加上lib,後面加上.so來確定庫的名稱

  • LD_LIBRARY_PATH:這個環境變量指示動態連接器可以裝載動態庫的路徑。
    當然如果有root權限的話,可以修改/etc/ld.so.conf文件,然後調用 /sbin/ldconfig來達到同樣的目的,不過如果沒有root權限,那麼只能採用輸出LD_LIBRARY_PATH的方法了。

參考文章:

https://www.cnblogs.com/huangxinzhen/p/4047051.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章