SO动态链接库文件的编译和使用
Posted 我想月薪过万
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SO动态链接库文件的编译和使用相关的知识,希望对你有一定的参考价值。
做C语言开发的都知道,在Linux环境中动态链接库以 .so结尾;在Windows环境中动态链接库以 .dll结尾。在讲使用之前,我先来给大家补补基础。
链接库分为 静态链接库 和 动态链接库。
静态链接库(a库):在 编译 的时候,库函数中函数的定义已经编译到源文件中,所以,静态链接库在编译完之后存不存在无关紧要。
动态链接库(so库):在 编译 的时候,库函数中函数的定义没有编译到源文件中,只是指定了库文件的路径,所以,编译之后源文件的执行还是依赖于so库文件。
静态链接库和动态链接库的区别在于,主程序在运行前,静态链接库的链接固定写入在程序中,而动态链接库则是在每次程序运行再加载链接。
如果对C语言编译 四步走 不熟悉的同学可以参考这篇文章 :微观的C/C++编译执行过程
在实际开发过程中,动态链接库用的居多,所以,我下面仅讲其的使用步骤:
代码示例
准备一个 .c 库函数文件
#include<stdio.h>
#include<stdlib.h>
int wust_test(int value){
printf("%d\\n",value);
}
在这里我建议大家也写一个 .h 文件,也就是你这个库函数里面包含 函数的一个申明,这样函数的含义 和 用法便一目了然了。如下:
//功能:测试 so 动态链接库
//参数一:整型
int wust_test(int value);
将这个库函数编译成 so 动态链接库
gcc test.c -fPIC -shared -o libtest.so
gcc 依赖库文件 -fPIC -shared -o libxxx.so
libxxx.so 必须以 lib 开头 .so结尾
-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),
则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意
位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
-shared 目的是使源码编译成动态库 .so 文件
这个时候 so动态链接库 就生成了,下面我们来看看调用
编写 main.c 文件
#include<stdio.h>
#include<stdlib.h>
int wust_test(int value);
int main(){
wust_test(33);
return 0;
}
编译 main.c 文件
gcc main.c -o main -L. -ltest
-L 指定依赖库文件所在的目录
-l 指定依赖库 libtest.so --> -ltest
执行 main
./main
这个时候你会发现报错:大概意思就是找不到库文件。解决方法如下:
将 so动态链接库文件路径赋值给环境变量 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$(pwd):
LD_LIBRARY_PATH:环境变量
pwd:当前目录的路径
::分隔符
再运行就可以了
SO文件调用原理回顾
大家看到这里就可以发现,动态链接库的创建和使用其实并不难。下面我将为大家梳理一下其中的思路。
我们在编写 main.c 的时候可以看到,和普通的 main.c 没太大区别,关键点在于 wust_test() 这个方法没实现;那这怎么办呢?动态链接库就起作用了。我们将 动态链接库文件所在路径 配置给 环境变量 LD_LIBRARY_PATH,所以,当系统在找 wust_test() 方法的实现的时候,就会找到这个库,所以请注意:你不配置是找不到滴。在编译的时候,我们也用到了动态链接库,-L指定库文件路径,-l指定库文件,你不指定也会报错。
以上是关于SO动态链接库文件的编译和使用的主要内容,如果未能解决你的问题,请参考以下文章
linux 下如何将动态链接库.so进行反编译后,换编译器重新编译?
LLINUX GCC 编译C使用自定义动态链接库.so的问题