1.介绍
在dlfcn.h头文件中,包含了dlopen,dlerror,dlsym,dlclose函数。函数原型如下:
#include <dlfcn.h>
//打开指定的动态库,返回的是该动态库的handle,在dlsym,dlclose中将继续使用。
void *dlopen(const char *filename, int flag);
//查看错误信息
char *dlerror(void);
//获得对应的函数或变量
void *dlsym(void *handle, const char *symbol);
//关闭打开的动态库
int dlclose(void *handle);
2.示例
2.1 调用系统动态库
/*************************************************************************
> File Name: foo.c
> Author: Jay
> Mail: jaytanfly@gmail.com
> Description:dlopen、dlsym、dlclose的学习使用,示例来自man dlopen,通过dlopen动态
调用cos函数,并算出cos2.0
************************************************************************/
#include <stdio.h>
#include <stdlib.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(EXIT_FAILURE);
}
dlerror(); /* 清楚之前存在错误信息 */
/*这里写成:cosine = (double (*)(double)) dlsym(handle, "cos");
或许会更自然一些,但是C99标准规定从“void *”转换为未定义的函数指针。
*/
*(void **) (&cosine) = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
/*打印cos2.0的值*/
printf("%f\n", (*cosine)(2.0));
dlclose(handle);
exit(EXIT_SUCCESS);
}
/*
编译:
gcc -rdynamic -o foo foo.c -ldl
运行:
./foo
输出:
-0.416147
*/
2.2 调用自己编写的动态库
/*************************************************************************
> File Name: hello.c
> Author: Jay
> Mail: jaytanfly@gmail.com
> Description:制作一个自己的动态链接库
************************************************************************/
#include <stdio.h>
char* name = "Jay";
int age = 25;
const char* get_name()
{
//printf("This is in Hello.c ");
return name;
}
void print_name()
{
printf("This is in Hello.c, name is : %s\n",name);
return;
}
int get_age()
{
//printf("This is in Hello.c ");
return age;
}
void print_age()
{
printf("This is in Hello.c, age is : %d\n",age);
return;
}
void set_age(int a)
{
age = a;
}
/*************************************************************************
> File Name: dlopen-test.c
> Author: Jay
> Mail: jaytanfly@gmail.com
> Description:调用hello.so
***********************************************************************/
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char** argv)
{
int i = 0;
void* handle;
void (*printName)();
void (*printAge)();
void (*setAge)(int a);
handle = dlopen("/动态库所在位置/hello.so",RTLD_LAZY);
if(!handle)
{
printf("%s %d, NULL == handle\n", __FUNCTION__, __LINE__);
return -1;
}
dlerror();
//获取print_name函数
*(void **) (&printName) = dlsym(handle, "print_name");
if(!printName)
{
printf("%s %d, NULL == printName\n", __FUNCTION__, __LINE__);
return -1;
}
(*printName)();
//获取print_age函数
*(void **) (&printAge) = dlsym(handle, "print_age");
if(!printAge)
{
printf("%s %d, NULL == printAge\n", __FUNCTION__, __LINE__);
return -1;
}
(*printAge)();
//获取set_age函数
*(void **) (&setAge) = dlsym(handle, "set_age");
if(!setAge)
{
printf("%s %d, NULL == printAge\n", __FUNCTION__, __LINE__);
return -1;
}
//设置age=30
(*setAge)(30);
//打印age
(*printAge)();
dlclose(handle);
return 0;
}
编译:
gcc -shared -o hello.so hello.c -fPIC
gcc -o test dlopen-test.c -ldl运行:
./test
输出:
This is in Hello.c, age is : 25
This is in Hello.c, age is : 30
3.总结
动态打开链接库,可以随时更新相关的库,并且不用修改主函数, 利用动态链接库完成相关功能的添加和删除,大大提高了灵活性。
版权声明:本文为博主原创文章,未经博主允许不得转载。原文链接:https://blog.csdn.net/ta_tan