Linux中編譯動態庫

類似Windows系統中的動態鏈接庫,Linux中也有相應的共享庫用以支持代碼的複用。Windows中爲*.dll,而Linux中爲*.so,我來詳細的告訴你如何在linux下編寫動態庫,以及如何使用它.

linux下編寫動態鏈接庫的步驟:

 

1.      編寫庫的頭文件和源文件.

2.      把所有涉及到的源文件用如下方式編譯爲目標文件:

 

g++/gcc -g -c -fPIC -o library1.o library1.cpp

g++/gcc -g -c -fPIC -o library2.o library2.cpp
      ......

......

(註釋:-fPIC指通過這個選項來生成與位置無關的代碼,可以在任何地址被連接和裝載,-c指只編譯而不連接原程序)

 

3.      把所有的目標文件鏈接爲動態庫:

 

g++/gcc -g -shared -Wl,-soname,lib***.so -o lib***.so.1.0.0 library1.o library2.o ....  -lc

                

    (註釋:-lc選項,表示使用c語言庫,一般都要用到)

 

4.      建立一個庫名鏈接

 

ln -s lib***.so.1.0.0 lib***.so

 

現在你就可以引用庫了.下面我分別給出簡單例子告訴你如何動態和靜態使用動態庫:

假如你的應用程序源代碼叫testlib.cpp

採用/如下方式編譯:

 

      g++ -g -o testlib testlib.cpp -ldl

            

    (註釋:-ldl選項,表示生成的對象模塊需要使用共享庫)

 

////////這個例子告訴你如何動態的調用.so庫

testlib.cpp

#include <dlfcn.h>

#include <iostream.h>

#include ...

int main()

{

       void *handle=NULL;

       //define a pointer which will point to the function in the lib you want to use.

       YourFuntionType (*pFunc)(YourFunctionPerameterList........);

       //open the lib you want to use.

       handle=dlopen("/../../../yourlib.so",RTLD_LAZY);

       if(handle==NULL)

       {

              cout<<"failed loading library!"<<endl;

              return -1;

       }

       dlerror();

       //try to load the function in lib

       pFunc=(YourFuntionType(*)(YourFunctionPerameterList))dlsym(handle,"YourFuntionName");

       if(dlerror()!=NULL)

       {

              cout<<"Loading function in lib error!"<<endl;

              return -1;

       }

       //now you can use the funtion like this

       (*pFunc)(YourFuntionPerameterList);

       return 0;

}  

 

(註釋:dlopen()

              第一個參數:指定共享庫的名稱,將會在下面位置查找指定的共享庫。

-環境變量LD_LIBRARY_PATH列出的用分號間隔的所有目錄。

-文件/etc/ld.so.cache中找到的庫的列表,用ldconfig維護。

-目錄usr/lib。

-目錄/lib。

-當前目錄。(這裏就是這種情況)

 

第二個參數:指定如何打開共享庫。

-RTLD_NOW:將共享庫中的所有函數加載到內存

-RTLD_LAZY:             會推後共享庫中的函數的加載操作,直到調用dlsym()時方加載某函數

dlsym()

          調用dlsym時,利用dlopen()返回的共享庫的phandle以及函數名稱作爲參數,返回要加載函數的入口地址。

       dlerror()

    該函數用於檢查調用共享庫的相關函數出現的錯誤。

 

特別需要注意的幾點問題:

1.      當你想用c++寫動態庫的時候,記住千萬別忘了在頭文件裏面加上如下內容,否則生成的庫在動態調用的時候會出問題!!!!!!!

 #ifdef __cplusplus
       extern "C" {

#endif

....

....

   #ifdef __cplusplus

}

#endif 

 

2.      當你的庫中包括與omniORB3相關的東西的時候,一定要在makefile中加上 -D__x86__ -D__OSVERSION=4

 

/////////////這個例子告訴你如何靜態調用.so庫

首先你得確保你的應用程序能夠找到你的.so庫,這可以有幾種方法來實現.

方法一:

1.你可以把YourLib.so.1.0.0 和YourLib.so放到/usr/lib中,然後執行命令:ldconfig,這樣你就可以在你的應用程序中直接調用你庫中的函數了,當然你 得把庫的頭文件包含到你的應用程序中

2.編譯你的應用程序

g++/gcc -g -o yourapp yourapp.cpp –lYourLib

 

方法二:

1.你也可以採用在系統中設置環境變量的辦法來實現. 在root目錄下:

vi .bash_profile

然後添加LD_LIBRARY=/../YourDirIncludingYourLib

然後注消一次,環境變量就生效了,這樣你就可以在你的應用程序中直接調用庫中的函數了,同樣你得有頭文件.

2.編譯你的應用程序

g++/gcc -g -o yourapp yourapp.cpp –lYourLib

 

方法三:

你可以直接採用在編譯鏈接的時候告訴系統你的庫在什麼地方
       g++/gcc -g -o yourapp yourapp.cpp -L/YourDirIncludingYourLib –lYourLib

/////////////////////////////////

假如你的庫中有個函數:int eat(.....)

那麼採用如下方式調用它

yourapp.cpp

#include "YourLib.h"

int main()

{

       eat();

return 0;

}

 

是不是很easy?對了在靜態調用的時候好像不存在上面的"注意1"的問題,不過鑑於保險起見,最好還是按照標準的方式寫c++頭文件吧,這絕對是個好習慣.

發佈了27 篇原創文章 · 獲贊 12 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章