首先设想一种情况,我们需要将某个功能做成可配置的,比如近期再弄的图形系统,风格应该是可配置的:在配置文件中用字符串记录使用到的“画法”库(这个“画法”就比如windows里面的开始按钮,“windows经典”风格是一个矩形,而“windows xp“风格则是一个圆角矩形,它们使用的绘图方法当然不一样),改动配置文件中“画法”库的路径、名字,就可以实现风格的可配置~~而且,根据既定的接口,还可以自由添加新的风格,不需要重新编译,只要把新写好的函数编译成库,改动配置文件中需要使用的库的路径和名字就ok了。
下面记下来这次实验用到的东西~
需要用到的函数:
#include <dlfcn.h>
void * dlopen(const char *file, int mode);
void * dlsym(void *restrict handle, const char *restrict name);
char * dlerror(void);
int dlclose(void *);
其中,
dlopen打开file路径下的共享库文件,返回这个共享库的操作指针handle。mode可取值有2个:RTLD_LAZY和RTLD_NOW, RTLD_LAZY就是第一次用到库中的函数时才进行重定位,RTLD_NOW就是马上咯~
dlsym将dlopen返回的handle中的name函数加载,将返回值赋值给我们声明的函数指针就是了~
dlerror返回这些过程中的错误信息,字符串~
dlclose,关闭已打开的共享库~
下面是个框架例子:
#include <stdio.h>
#include <dlfcn.h>
int main()
{
int (* my_function)(int); /* 声明一个函数指针,用来指向要加载的共享库中的函数 */
char * error; /* 用来记录错误信息 */
void * handle; /* 这个指针指向打开的库 */
char * libfile; /* 要打开的库的路径、文件名 */
init others
handle = dlopen(file, RTLD_LAZY); /* 打开库 */
if (!handle)
{
printf("%s/n", dlerror());
return 1;
}
my_function = dlsym(handle, "function"); /* 将库中的function函数加载到my_function指针 */
if ((error = dlerror()) != NULL)
{
printf("%s/n", error);
dlclose(handle);
exit(2);
}
*my_function(2); /* 调用库中的函数 */
dlclose(handle); /* 正常关闭库 */
return 0;
}
这个框架中,假定打开的库中有一个定义为【 int function(int) 】 的函数,我们声明了一个与之对应的函数指针,实现动态加载和调用。