so库调用
1.动态调用
//my.h void test();
//my.c
#include<stdio.h>
void test()
{
printf("This is a test\n");
}
//main.c
#include "my.h"
int main(int argc, char* argv[]){ test(); return 0; }
动态库调用
muhe221@muhe:~/work/lib$ gcc -c my.c
muhe221@muhe:~/work/lib$ ls
main.c my.c my.h my.o
muhe221@muhe:~/work/lib$ gcc -fpic -shared -o libmy.so my.c
muhe221@muhe:~/work/lib$ ls
libmy.so main.c my.c my.h my.o
muhe221@muhe:~/work/lib$ gcc main.c -L. -lmy -o main.o // -o main.o必须放最后面 否则报错 why?
muhe221@muhe:~/work/lib$ ls
libmy.so main.c main.o my.c my.h my.o
muhe221@muhe:~/work/lib$ ./main.o
./main.o: error while loading shared libraries: libmy.so: cannot open shared object file: No such file or directory
muhe221@muhe:~/work/lib$ sudo cp libmy.so /lib
muhe221@muhe:~/work/lib$ ./main.o
This is a test
muhe221@muhe:~/work/lib$
编译生成动态库文件,要加上 -shared 和 -fpic 选项 ,库文件名以lib开头, 以.so 结尾。
-L 指定函数库查找的位置,注意L后面还有'.',表示在当前目录下查找
If supported for the target machine, emit position-independent code, suitable for dynamic linking and
avoiding any limit on the size of the global offset table. This option makes a difference on the m68k,
PowerPC and SPARC.
Position-independent code requires special support, and therefore works only on certain machines.
When this flag is set, the macros "__pic__" and "__PIC__" are defined to 2.
静态库调用
muhe221@muhe:~/work/lib$ ls
main.c my.c my.h
muhe221@muhe:~/work/lib$ gcc -c my.c
muhe221@muhe:~/work/lib$ ls
main.c my.c my.h my.o
muhe221@muhe:~/work/lib$ ar -rc libmy.a my.o
muhe221@muhe:~/work/lib$ ls
libmy.a main.c my.c my.h my.o
muhe221@muhe:~/work/lib$ gcc -l . -o main.o -c main.c
muhe221@muhe:~/work/lib$ ls
libmy.a main.c main.o my.c my.h my.o
muhe221@muhe:~/work/lib$ gcc -o main -L. main.o -lmy
muhe221@muhe:~/work/lib$ ls
libmy.a main main.c main.o my.c my.h my.o
muhe221@muhe:~/work/lib$ ./main
This is a test
muhe221@muhe:~/work/lib$
-------------------------------------------------------------------------------------------------------------------------------
为了使程序方便扩展,具备通用性,可以采用插件形式。采用异步事件驱动模型,保证主程序逻辑不变,将各个业务已动态链接库的形式加载进来,这就是所谓的插件。linux提供了加载和处理动态链接库的系统调用
//calc.c int add(int a,int b) { return (a + b); } int sub(int a, int b) { return (a - b); } int mul(int a, int b) { return (a * b); } int div(int a, int b) { return (a / b); }
//main.c #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> //动态链接库路径 #define LIB_CACULATE_PATH "./libcalculate.so" //函数指针 typedef int (*CAC_FUNC)(int, int); int main() { void *handle; char *error; CAC_FUNC cac_func = NULL; //打开动态链接库 handle = dlopen(LIB_CACULATE_PATH, RTLD_LAZY); if (!handle) { fprintf(stderr, "%s\n", dlerror()); exit(EXIT_FAILURE); } //清除之前存在的错误 dlerror(); //获取一个函数 cac_func = dlsym(handle, "add"); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); exit(EXIT_FAILURE); } printf("add: %d\n", (*cac_func)(8, 2)); cac_func = (CAC_FUNC)dlsym(handle, "sub"); printf("sub: %d\n", cac_func(8, 2)); cac_func = (CAC_FUNC)dlsym(handle, "mul"); printf("mul: %d\n", cac_func(8, 2)); cac_func = (CAC_FUNC)dlsym(handle, "div"); printf("div: %d\n", cac_func(8, 2)); //关闭动态链接库 dlclose(handle); exit(EXIT_SUCCESS); }
dlopen以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程,dlerror返回出现的错误,dlsym通过句柄和连接符名称获取函数名或者变量名,dlclose来卸载打开的库。 dlopen打开模式如下:
RTLD_LAZY 暂缓决定,等有需要时再解出符号
RTLD_NOW 立即决定,返回前解除所有未决定的符号。
muhe221@muhe:~/test/test/nel$ ls calc.c main.c muhe221@muhe:~/test/test/nel$ gcc -fpic -shared -o libcalculate.so calc.c muhe221@muhe:~/test/test/nel$ ls calc.c libcalculate.so main.c muhe221@muhe:~/test/test/nel$ gcc -rdynamic -o main main.c -ldl muhe221@muhe:~/test/test/nel$ ls calc.c libcalculate.so main main.c muhe221@muhe:~/test/test/nel$ ./main add: 10 sub: 6 mul: 16 div: 4

浙公网安备 33010602011771号