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