方法一:通过gcc编译命令指定“-l+库名”来链接动态库
假设我编写了一个函数,函数体如下:
#include "stdio.h"
void test_a()
{
printf("this is in test_a...\n");
}
在makefile中将如上函数封装成动态库的命令为:
libtest.so:test_a.c
gcc $^ -fPIC -shared -o $@
通过执行make libtest.so,就能够得到动态库libtest.so。
当我想要在另外一个程序main.c中使用它时,需要在程序内声明:
extern void test_a();
同时,在MakeFile中进行链接:
VPATH=src include
CROSS := gcc
CFLAG := -L ./ -ltest -Wl,-rpath=./
main:main.o
$(CROSS) obj/main.o $(CFLAG) -o main
main.o:main.c
$(CROSS) -Wall -std=c99 -I include -c $< -o obj/main.o
这样就能够在main.c中运行libtest.so动态库函数中的test_a()函数。
方法二:通过dlopen来使用动态库
该方法使用动态库不需要加入链接动态库“-ltest”的指令,程序在运行的时候也会自动加载动态库,有点像fopen打开文件,当你需要这个动态库的时候,用dlopen打开它就好了。
完整代码
#include <stdio.h>
#include <dlfcn.h> //dlopen需要的头文件
int main()
{
void *handle = dlopen("libtest.so", RTLD_LAZY); //RTLD_LAZY:延迟加载,什么时候真正使用的时候才加载
if(handle == NULL)
{
printf("handle is NULL\n");
}
void (*test_a)();
test_a = dlsym(handle, "test_a"); //参数1:动态库句柄,参数2:函数名
if(test_a != NULL)
{
test_a();
}
else
{
printf("test_a is Null ptr\n");
}
dlclose(handle);
return 0;
}
生成动态库的命令是一样的:
libtest.so:test_a.c
gcc $^ -fPIC -shared -o $@
生成main执行程序的MakeFile如下:
VPATH=src include
CROSS := gcc
CFLAG := -L ./ -ldl -Wl,-rpath=./
main:main.o
$(CROSS) obj/main.o $(CFLAG) -o main
main.o:main.c
$(CROSS) -Wall -std=c99 -I include -c $< -o obj/main.o
libtest.so:test_a.c
$(CROSS) $^ -fPIC -shared -o $@
.PHONY: clean
clean:
rm -rf *.o obj/*.o *.a main
需要注意的是,dlopen函数去搜索动态库的路径是按照动态库搜索路径找的:
动态链接时、执行时搜索路径顺序:
1. 编译目标代码-L时指定的动态库搜索路径
2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径
4. 默认的动态库搜索路径/lib
5. 默认的动态库搜索路径/usr/lib
而本程序中生成的动态库libtest.so是在根目录下的,同时我们在makefile中通过-Wl,-rpath=./指令将根目录加入了动态链接库的搜索路径,因此在main.c程序中我们不能写动态库的绝对路径,例如"/home/testcode/libtest.so",而应该直接写“dlopen("libtest.so", RTLD_LAZY)”,这样才能找到。
|