以下例項的環境是amd64 + ubuntu10.10 + g++ 4.4.5測試成功,在其他配置的機器上可能有一點區別。
動態庫的使用方式中有兩種,第一種是類似於靜態庫的使用,另一種我稱之為真正的動態載入動態庫,主要是因為這種方式在程式執行的過程中載入鏈結庫,使用之後在解除安裝鏈結庫。
先介紹第一種。
在目錄/home/owner/test/下建立我們的實驗程式:
//dll_fun.c
#include
void dll_function(const char* szstring)
編譯生成動態鏈結庫
gcc -c -fpic dll_fun.c //這裡一定要加上-fpic選項,不然下一步編譯失敗
gcc -shared -fpic -o libdllfun.so dll_fun.o //生成動態鏈結庫libdllfun.so
建立呼叫動態庫方法:
void dll_function(const char* szstring);
int main()
編譯main.c生成可執行檔案
gcc -o main main.c -l. -ldllfun //這裡提供了剛才生成的dllfun庫
如果此時執行./main的話,會出現如下錯誤:
cannot open shared object file: no such file or directory
這是因為系統未找到動態庫libdllfun.so。
linux動態鏈結庫的預設搜尋路徑是/lib和/usr/lib,因此動態庫被建立後,一般都複製到這兩個目錄下面,當程式執行時需要某動態庫,並且改動態庫還沒有載入到記憶體中,則系統會自動到這兩個預設的搜尋路徑中去查詢相應的動態庫檔案,然後載入改檔案到記憶體中,這樣程式就可以使用該動態庫中的函式以及該動態庫中的其他資源了。在linux中,動態庫的搜尋路徑除了預設的搜尋路徑外,還可以通過其他三種方法來指定,這裡只介紹其中的一種:通過環境變數ld_library_path指定動態庫搜尋路徑。
當通過該環境變數指定多個動態鏈結庫搜尋路徑時,路徑之間用冒號":"分隔。
使用下面命令來配置環境
mkdir /home/owner/test/lib//將這個目錄設定為動態庫的存放目錄
mkdir/home/owner/test/libdllfun.so /home/owner/test/lib/libdllfun.so
export ld_library_path=/home/owner/test/lib
此時設定這個環境變數之後的所有命令命令中,該環境變數都有效。
./main
可得如下結果:
this is the words of the dll function!!!!!!
第二種載入動態庫例項:
//dll_fun.c
#include
void dll_function(const char* szstring)
編譯該檔案:
gcc -wall -fpic -c dll_fun.c
gcc -shared -w1,-soname,libdllfun.so.1 -o libdllfun.so.1.0 *.o
sudo mv libdllfun.so.1.0 /usr/lib
sudo ln -sf /usr/lib/libdllfun.so.1.0 /usr/lib/libdllfun.so
sudo ln -sf /usr/lib/libdllfun.so.1.0 /usr/lib/libdllfun.so.1
引數詳解:
-wall:包含warning資訊
-fpic:編譯動態庫所必須的,輸出不依賴位置的**
-shared:編譯動態庫必須選項
-w1:向聯結器傳遞一些引數,在這裡傳遞的引數有「-soname」,"libdllfun.so.1"
-o:動態庫的名字,在這個例子裡最終生成動態庫libdllfun.so.1.0
第乙個:允許應用**用-dllfun的語法進行編譯
第二個:允許應用程式在執行時呼叫動態庫
下面是簡單的動態呼叫so的例子:
增加dll_fun.h:
//dll_fun.h
#ifndef _dll_fun_h_
#define _dll_fun_h_
#ifdef __cplusplus
extern "c"
#endif
#endif
這裡我們仍然使用之前生成的libdllfun.so.1.0,增加乙個新的應用程式cprog.c
#include
#include //dlopen, dlsym, dlerror, dlclose的標頭檔案
#include
#include "dll_fun.h"
//此例為動態載入動態庫
int main()
return 0; }
用如下命令編譯執行:
gcc -wall cprog.c -ldllfun -ldl -o cprog
./cprog
方法簡介:
dlopen("libdllfun.so", rtld_lazy):載入動態庫,如果載入失敗返回null,第二個引數可能有:
rtld_lazy:lazy模式,直到程式執行到該行才嘗試載入
rtld_now:馬上載入
rtld_global:make symbol libraries visible
在這種方式下不知道怎麼修改動態鏈結庫搜尋路徑,網上的一種方法是採用修改/etc/ld.so.conf,我試了一下,好像效果不是很好,而且要修改這個檔案,感覺總不是太好,而且一樣的麻煩,希望有那個好心人能夠提供乙個比較好的方法,讓我也學習一下,謝謝了:)。
ldd cprog
可得如下結果:
linux-vdso.so.1 => (0x00007fff831ff000)
libdllfun.so => /usr/lib/libdllfun.so (0x00007fa1798df000)
libdl.so.2 => /lib/libdl.so.2 (0x00007fa1796db000)
libc.so.6 => /lib/libc.so.6 (0x00007fa179357000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa179afc000)
使用命令nm檢視輸出函式:
nm libdllfun.so
編譯命令簡介:
假設c檔案是cprog.c,c++呼叫檔案是cppprog.cpp,則編譯指令碼分別是:
c語言:
gcc -wall -i/path/to/include/headers -l/path/to/libraries cprog.c -ldllfun -ldl -o cprog
c++語言:
g++ -wall -i/path/to/include/headers -l/path/to/libraries cppprog.cpp -ldllfun -ldl -o cppprog
引數詳解:
-i:指定頭檔案目錄
-l:指定庫目錄
c++開發帶class的動態庫
以下幾個檔案
#ifndef __myclass_h__
#define __myclass_h__
class myclass ;
#endif
#include "myclass.h"
#include
using namespace std;
extern "c" myclass* create_object()
extern "c" void destroy_object(myclass* object)
myclass::myclass()
void myclass::dosomething()
#include
#include
#include "myclass.h"
using namespace std;
int main(int argc, char **ar**)
編譯和執行
g++ -fpic -shared myclass.cpp -o myclass.so
g++ classuser.cpp -ldl -o classuser
./classuser
ubuntu下動態鏈結庫的編譯和使用
環境 uabntu 14.04 1.設定從當前目錄下載入動態庫so檔案 ld library path linux的excutable在執行的時候預設是先搜尋 lib和 usr lib這兩個目錄,然後按照ld.so.conf裡面的配置搜尋絕對路徑,linux預設是不會在當前目錄搜尋動態庫的。1 臨時...
ubuntu下動態鏈結庫的編譯和使用例項
以下例項的環境是amd64 ubuntu10.10 g 4.4.5測試成功,在其他配置的機器上可能有一點區別。動態庫的使用方式中有兩種,第一種是類似於靜態庫的使用,另一種我稱之為真正的動態載入動態庫,主要是因為這種方式在程式執行的過程中載入鏈結庫,使用之後在解除安裝鏈結庫。先介紹第一種。在目錄 ho...
ubuntu下動態鏈結庫的編譯和使用例項
以下例項的環境是amd64 ubuntu10.10 g 4.4.5測試成功,在其他配置的機器上可能有一點區別。動態庫的使用方式中有兩種,第一種是類似於靜態庫的使用,另一種我稱之為真正的動態載入動態庫,主要是因為這種方式在程式執行的過程中載入鏈結庫,使用之後在解除安裝鏈結庫。先介紹第一種。在目錄 ho...