动态链接有两种类型,一种是程序加载时链接,另一种是程序运行时链接,以下分别是两个例子
- 程序加载时链接
//test_so_1.c
//需要include dlfcn.h
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
void *handle;
void (*myfunc1)();
char *error;
//open the so
handle = dlopen("./dll.so", RTLD_LAZY);
if (!handle)
{
fprintf(stderr, "%s \n", dlerror());
exit(1);
}
//get the function from so
myfunc1 = dlsym(handle, "func1");
if ((error = dlerror()) != NULL)
{
fprintf(stderr, "%s\n", error);
exit(1);
}
//use the function from so with local pointer
myfunc1();
//close the so
if (dlclose(handle) < 0)
{
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
return 0;
}
- 程序运行时链接
//test_so_2.c
void func1();
int main()
{
func1();
return 0;
}
- 所链接的共享库代码
//dll.c
#include <stdio.h>
void func1()
{
fputs("This is from func1 in dll.c\n", stdout);
}
test_so_1.c和test_so_2.c均能实现动态链接,但是在使用gcc编译时有所不同。
首先需要先编译共享库,即dll.c
gcc -shared -fPIC dll.c -o dll.so
其中-shared表示生成共享库目标文件,-fPIC表示生成与位置无关的代码(Position Independent Code)。
其次分别编译test_so_1.c和test_so_2.c。
对于test_so_1.c
gcc -rdynamic test_so_1.c -o test_so_1 -ldl
其中-rdynamic表示要使用共享库(动态链接库)中的函数,-ldl表示采用动态连接器接口中的dlsym等函数进行链接。
对于test_so_2.c
gcc test_so_2.c ./dll.so -o test_so_2
通过上述操作,即可得到两个可执行目标文件test_so_1和test_so_2,均可正常调用dll.so中的函数。所不同的是,test_so_1是在程序执行的过程中链接,而test_so_2是在程序运行时,加载器会调用动态链接器完成链接,重新生成完全链接可执行目标文件。