Linux静态库与动态库实例详解
时间:2022-07-27
本文章向大家介绍Linux静态库与动态库实例详解,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Linux静态库与动态库实例详解
1. Linux 下静态链接库编译与使用
首先编写如下代码:
// main.c
#include "test.h"
int main(){
test();
return 0;
}
// test.h
#include<iostream>
using namespace std;
void test();
// test.c
#include "test.h"
void test(){
cout<< "test!" <<endl;
}
然后编译:
1. gcc -c test.c //生成目标文件 2. ar crv libtest.a test.o //生成静态链接库libtest.a 3. g++ -o main main.c -ltest //编译main程序同时链接libtest.a静态库 4. ./main //运行main程序
2. Linux 下动态链接库编译与使用
代码与上述一致。
然后编译:
1. g++ -fPIC -shared -o libtest.so test.c //生成动态链接库libtest.so 2. g++ -o main main.c -ltest //调用动态链接库libtest.so 3. ./main //运行main程序
3. 链接时缺失了相关目标文件(.o)
代码与上述一致。
编译过程如下:
1. gcc -c test.c 2. gcc -c main.c 3. gcc -o main main.o
这时,你会发现,报错了:undefined reference to `test’.
这就是最典型的 undefined reference 错误,因为在链接时发现找不到某个函数的实现文件, 本例中test.o文件中包含了test()函数的实现,所以如果按下面这种方式链接就没事了。
1. gcc -o main main.o test.o
【扩展】:其实上面为了让大家更加清楚底层原因,我把编译链接分开了,下面这样编译
也会报undefined reference错,其实底层原因与上面是一样的。
gcc -o main main.c //缺少test()的实现文件
需要改成如下形式才能成功,将test()函数的实现文件一起编译。
gcc -o main main.c test.c //ok,没问题了
4. 链接时缺少相关的库文件(.a/.so)
在此,只举个静态库的例子,假设源码与上述一致。
1. 把test.c编译成静态库:
gcc -c test.c
sr -rc test.a test.o
gcc -c main.c
2. 生成可执行程序:
gcc -o main -main.o
此时同样出现 undefined reference to `test'报错。其根本原因也是找不到test()函数的实现文
件,由于该test()函数的实现在test.a这个静态库中的,故在链接的时候需要在其后加入test.a这个
库,链接命令修改为如下形式即可。
1. gcc -o main main.c ./test.a
5. 多个库文件链接顺序问题
这种问题也非常的隐蔽,不仔细研究你可能会感到非常地莫名其妙。我们依然回到第3小节所讨论
的问题中,在最后,如果我们把链接的库的顺序换一下,看看会发生什么结果?
1. gcc -o main main.o func.a test.a
我们会得到如下的编译错误:
1. test.a(test.o): In function `test':
2. test.c:(.text+0x13): undefined reference to `func'
3. collect2: ld returned 1 exit status
因此,我们需要注意,在链接命令中给出所依赖的库时,需要注意库之间的依赖顺序,依赖其他库
的库一定要放到被依赖库的前面,这样才能真正避免undefined reference的错误,完成编译链接。
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
- Android内存优化(二)DVM和ART的GC日志分析
- Android Material Design之Toolbar与Palette实践
- android-async-http框架源码分析
- 使用Buck构建Android工程
- android 实现淘宝收益图的折线
- React Native入门(三)组件的Props(属性)和State(状态)
- Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)【Dalston版】
- PNG图片压缩对比分析
- 关于M4A文件的随机访问
- (whh仅供自己参考)进行ip网络请求的步骤
- HTML中的javascript交互
- Spring Cloud构建微服务架构:分布式配置中心【Dalston版】
- [Android] Toast问题深度剖析(二)
- [Android] Toast问题深度剖析(一)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Flutter开发之路由与导航的实现
- Android BSearchEdit 搜索结果选择框的实例代码
- 使用AccessibilityService实现微信自动切换账号功能
- Android评分RationBar控件使用详解
- Flutter里面错误捕获的正确方法
- django3 websockets
- 使用AccessibilityService实现自动遍历点赞功能
- Android自定义字母导航栏
- [-Flutter 自组篇-] 圆形进度条
- Flutter 滚动监听及实战appBar滚动渐变的实现
- Android 开机充电图标和充电动画效果
- 使用tea算法对数据进行加密
- Android实现页面翻转和自动翻转功能
- Android实现自定义手势和识别手势的功能
- android 使用okhttp可能引发OOM的一个点