類似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++標頭檔吧,這絕對是個好習慣.