一、动态库的静态加载
1.编译动态库->链接成共享库
gcc -fpic -c math.c -o math.o //自行编写他们的头文件放在同一目录下
gcc -fpic -c show.c -o show.o
gcc -shared math.o show.o -o libmath.so //libmath.so为动态库,libxxx其中 xxx 为动态库的名字
2.将动态库的路径加到环境变量中
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. //.表示当前目录
3.生成可执行程序并运行
gcc main.c libmath.so -o math //生成math,运行./math
或
gcc main.c -L./ -lmath -o math
二、动态库的动态加载
动态加载是在程序运行期间加载和卸载动态库。Linux中的dl库实现库的动态加载。最终链接时,使用-ldl。
#include <dlfcn.h>
void *dlopen(const char *filename,int flag);
char *dlerror(void);
void *dlsym(void *handle,const char *symbol);
int dlclose(void *handle);
Link with -ldl
1.加载共享库---dlopen
void *dlopen(const char *filename,int flag);
--filename:如果有路径,按照路径加载;只有文件名时,根据LD_LIBRARY_PATH环境变量去查找
--flag:加载标志(RTLD_LAZY:延迟加载,什么时候真正使用,什么时候加载;RTLD_NOW:立即加载)
--返回值:成功返回动态库的句柄,失败返回NULL
2.获取动态库的函数地址---dlsym
void *dlsym(void *handle,const char *symbol);
--handle:动态库的句柄
--symbol:函数名
--返回值:成功返回函数地址,失败返回NULL
3.卸载动态库---dlclose
int dlclose(void *handle);
--handle:动态库句柄
4.获取出错信息--dlerror
char *dlerror(void);
--返回值:返回错误字符串
例子:
#include<stdio.h>
#include<dlfcn.h>
typedef int(*PFUNC_CALL)(int,int);
typedef int(*PFUNC_SHOW)(int); //给函数指针定义一个别名 PFUNC_SHOW = int(*)(int)
int main()
{
void *handle = dlopen("./libmath.so",RTLD_LAZY); //加载动态库
if(handle==NULL)
{
printf("dlopen失败:%s\n",dlerror());
return -1;
}
//获取函数地址
PFUNC_CALL add = (PFUNC_CALL)dlsym(handle,"add");
if(add==NULL)
{
printf("dlsym失败:%s\n",dlerror());
return -1;
}
int(*show)(int)= dlsym(handle,"show"); //int(*show)(int) = PFUNC_SHOW
if(add==NULL) // 函数原型 int show(int)
{
printf("dlsym失败:%s\n",dlerror());
return -1;
}
show(add(9,5));
dlclose(handle);
return 0;
}
编译链接:
gcc dmain.c -ldl -o math
三、静态库
1.编译静态库
gcc math.cpp -c //生成math.o
ar rc math.a math.o //生成math.a
2.链接静态库
gcc main.cpp math.a -o main