dlopen()是一個強大的庫函數。該函數將開啟一個新庫,並把它裝入記憶體。該函數主要用來載入庫中的符號,這些符號在編譯的時候是不知道的。比如 Apache Web 服務器利用這個函數在運行過程中載入模組,這為它提供了額外的能力。一個設定檔控制了載入模組的過程。這種機制使得在系統中添加或者刪除一個模組時,都不需要重新編譯了。
當動態連結程式庫操作函數執行失敗時,dlerror可以返回出錯資訊,傳回值為NULL時表示操作函數執行成功。
LINUX建立與使用動態連結程式庫並不是一件難事。
編譯函數來源程式時選用-shared選項即可建立動態連結程式庫,注意應以.so尾碼命名,最好放到公用庫目錄(如/lib,/usr/lib等)下面,並要寫好使用者介面檔案,以便其它使用者共用。
使用動態連結程式庫,來源程式中要包含dlfcn.h標頭檔,寫程式時注意dlopen等函數的正確調用,編譯時間要採用-rdynamic選項與-ldl選項 ,以產生可調用動態連結程式庫的執行代碼。
我們這裡要聊的是,對dlsym傳回值的判斷。
cosine = dlsym(handle, "cos"); //cos便是符號
If the symbol is not found, in the specified library or any of the libraries that were automati-cally loaded by dlopen() when that library was loaded, dlsym() returns NULL. (The search performed by dlsym() is breadth first through the dependency tree of these libraries.) Since the value of the symbol could actually be NULL (so that a NULL return from dlsym() need not indicate an error), the correct way to test for an error is to call dlerror() to clear any old error conditions, then call dlsym(), and then call dlerror() again, saving its return value into a variable, and check whether this saved value is not NULL.
寫法如:
① dlerror();
② a_func_name = ...dlsym(...);
③ if (dlerror()) goto end;
④ a_func_name(...);
樣本:
不過,實際中,也常有這種寫法:
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL)
{
fprintf (stderr, "%s\n", error);
exit(1);
}
樣本
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv)
{
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("libm.so", RTLD_LAZY);
if (!handle)
{
fprintf (stderr, "%s\n", dlerror());
exit(1);
}
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL)
{
fprintf (stderr, "%s\n", error);
exit(1);
}
printf ("%f\n", (*cosine)(2.0));
dlclose(handle);
return 0;
}
gcc -rdynamic -o foo foo.c -ldl
原文
[1]http://blog.csdn.net/jernymy/article/details/6903683
[2]http://www.9php.com/FAQ/cxsjl/c/2006/12/710159053564.html
[3]http://linux.about.com/library/cmd/blcmdl3_dlsym.htm
[4]http://stackoverflow.com/questions/13941944/why-can-the-value-of-the-symbol-returned-by-dlsym-be-null