linux动态加载库
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