linux 的动态链接文件叫so 是 share object的意思。
编译使用参数 -fPIC 是 Position Independent Code 位置无关代码
gcc hello.c -fPIC -shared -o libhello.so
动态加载
为引用libhello.so, 编译main.cs时用下面命令
gcc main.c -L. -lhello -o main
编译后不能运行需要设置参数:
export LD_LIBRARY_PATH+=LD_LIBRARY:$(pwd)
例如:
1,做 hello.c,有函数 say(){printf("hello world!");}
编译 gcc hello.c -fPIC -shared -o libhello.so
2,hello.h文件定义 void say(); main.c文件引用 #include“hello.c”。
并且在int main(int argc, char** argv)中使用sayn()。
编译:gcc main.c -L. -lhello -o main
运行./main 输出 hello world!;
3,做byebye.c,有函数 say(){printf("byebye world!");}
编译 gcc byby.c -fPIC -shared -o libhello.so
运行./main 输出 byebye world!
上面实验可以得出动态引用的特性。也就是so文件的内容不编译进可执行程序中。
动态加载的实质是:在程序实例化时(为运行时做准备时)动态加载so中内容。
动态调用
除动态加载so文件外。还可以动态调用so中的函数。
动态调用方法使用 dlfcn.h中的方法。并且编译时使用libbl.so进行编译。
以dyn_main.c为例 编译方法如下:(dyn_main方法在后面)
gcc dyn_main.c -L. -ldl -o dyn_main
编译后运行 ./dyn_main
输出:根据hello.so中say方法决定。
/************ dyn_main.c **************/
#include<dlfcn.h> //动态调用框架的头文件
#include"hello.h"
#include<stdio.h>
int main(int argc, char** argv) {
void(*say)();
//加载动态库
void* handle = dlopen("libhello.so", RTLD_LAZY);
if(handle == NULL ) {
printf("Failed load library\n");
return -1;
}
char* err = dlerror();
if(err != NULL)
{
printf("%s\n", err);
return -1;
}
//得到函数的地址
say = dlsym(handle, "say");
err = dlerror();
if(err != NULL)
{
printf("%s\n", err);
dlclose(handle);
return -1;
}
}