Linux 調用(yong)動態庫(.SO文件)總(zong)結(jie)
前面一篇文章“VS2010 C++創建、調用DLL圖解”簡單講(jiang)述了在(zai)Windows下創建和(he)調(diao)用動態(tai)庫(.dll文件)方法,本篇(pian)結合項目(mu)過(guo)程,總(zong)結一下Linux下調(diao)用動態(tai)庫(.so文件)的方法和(he)注意(yi)點。
像window調用庫(ku)文件一樣(yang),在(zai)linux下,也(ye)有(you)相應的(de)API因為加載(zai)庫(ku)文件而存(cun)在(zai)。它們(men)主要是以下幾個函數:
| 函數名 | 功(gong)能描述(shu) |
|---|---|
| dlopen | 打開對象文(wen)件,使其可被(bei)程序訪問 |
| dlsym | 獲取執行了 dlopen 函數的對象文件中的函數的地址 |
| dlerror | 該(gai)函(han)數(shu)沒有參數(shu),它會在(zai)發生(sheng)前面的錯誤時返回一個字符(fu)串,同時將其從內存中清空; 在(zai)沒有錯誤發生(sheng)時返回 NULL, |
| dlclose |
關閉目標文件。如果無需再調用共享對象的話,應用程序可以調用該方法來通知操作系統不再需要句柄和對象引用了。它完全是按引用來計數的,所以同一個共享對象的多個用戶相互間不會發生沖突(只要還有一個用戶在使用它,它就會待在內存中)。任何通過已關閉的對象的 |
實例(li)代碼(soTest.c):
1 #include <stdio.h> 2 #include <dlfcn.h> 3 4 int main(int argc, char *argv[]){ 5 void * libm_handle = NULL; 6 float (*cosf_method)(float); 7 char *errorInfo; 8 float result; 9 10 // dlopen 函數還(huan)會(hui)自動(dong)解析共享庫(ku)中的依(yi)賴(lai)項。這樣,如果您打開了一(yi)個依(yi)賴(lai)于(yu)其(qi)他共享庫(ku)的對象,它就會(hui)自動(dong)加載它們。 11 // 函(han)數返回一(yi)個句(ju)柄,該(gai)句(ju)柄用于后續的 API 調(diao)用 12 libm_handle = dlopen("libm.so", RTLD_LAZY ); 13 // 如(ru)果返回(hui) NULL 句(ju)柄,表(biao)示(shi)無法找到(dao)對象(xiang)(xiang)文件,過程結(jie)束。否則的話,將(jiang)會(hui)得到(dao)對象(xiang)(xiang)的一個(ge)句(ju)柄,可以(yi)進一步詢問對象(xiang)(xiang) 14 if (!libm_handle){ 15 // 如(ru)果(guo)返回 NULL 句柄,通過dlerror方法可以取得(de)無法訪問對象的原因 16 printf("Open Error:%s.\n",dlerror()); 17 return 0; 18 } 19 20 // 使用 dlsym 函(han)數(shu),嘗(chang)試(shi)解析新打開的(de)對象文件中的(de)符(fu)號。您將會得(de)到(dao)一個有效的(de)指向該符(fu)號的(de)指針,或者是得(de)到(dao)一個 NULL 并返回一個錯誤 21 cosf_method = dlsym(libm_handle,"cosf"); 22 errorInfo = dlerror();// 調(diao)用(yong)dlerror方法,返回錯(cuo)誤信息(xi)的同時,內存中的錯(cuo)誤信息(xi)被清(qing)空 23 if (errorInfo != NULL){ 24 printf("Dlsym Error:%s.\n",errorInfo); 25 return 0; 26 } 27 28 // 執行“cosf”方(fang)法 29 result = (*cosf_method)(0.0); 30 printf("result = %f.\n",result); 31 32 // 調用 ELF 對象(xiang)中(zhong)的目(mu)標函數后,通過調用 dlclose 來關(guan)閉對它的訪問 33 dlclose(libm_handle); 34 35 return 0; 36 }
在這個例子中主(zhu)要(yao)(yao)是調用(yong)了 math 庫(ku)(libm.so)中的(de)(de)“cosf”函(han)數,dlopen函(han)數的(de)(de)第(di)二(er)個參數表示加載庫(ku)文件的(de)(de)模式,主(zhu)要(yao)(yao)有(you)兩種:RTLD_LAZY 暫緩決(jue)定,等(deng)有(you)需要(yao)(yao)時再解(jie)出(chu)符(fu)(fu)號;RTLD_NOW 立即決(jue)定,返回前(qian)解(jie)除(chu)所有(you)未決(jue)定的(de)(de)符(fu)(fu)號。另外記得引(yin)用(yong)包含API的(de)(de)頭文件“#include <dlfcn.h>”(^_^)。
編譯執(zhi)行(xing)結果如(ru)下:

如果將代(dai)碼12行中(zhong)的(de)(de)庫文件(jian)名改為一個不(bu)存在的(de)(de)庫文件(jian),運行后錯(cuo)誤(wu)結果如下(xia):

如果將代碼21行(xing)中的(de)函數名改為一個(ge)不(bu)存在(zai)的(de)函數名,運行(xing)后(hou)錯(cuo)誤結果如下:

本文(wen)主要簡單講(jiang)述在linux下調用SO庫文(wen)件的一些基(ji)本知識和(he)注(zhu)意點(dian)。
本實例在redhat 5.2的64系統下測試通(tong)過。
歡迎轉載,請注明出處!
感謝您的閱讀,請關注后續博客!
共享視頻教程請訪問:
