博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux系统编程25:基础IO之亲自实现一个动静态库
阅读量:188 次
发布时间:2019-02-28

本文共 2155 字,大约阅读时间需要 7 分钟。

本文接:

文章目录

A:说明

前面说过,库其实就是头文件和和.a.so文件的集合,而.a.so文件则是由众多.o文件打包而成(不太准确)。所以只要有我的头文件和.o文件,使用者就可以使用我的代码了

如下我有两个文件一个是mylib.h,一个是mylib.c,目的是写一个自己的打印函数

在这里插入图片描述
代码如下

//mylib.h#include 
void Myprintf();//mylib.c#inlude "mylib.h"void Myprintf(){
printf("Hello World\n");}

接着要使用gcc -c生成.o文件

在这里插入图片描述
接着新建一个目录test,将mylib.o和,mylib.h文件拷贝至该目录下
在这里插入图片描述
接着在该目录下建立一个test.c文件,该文件就可以通过引入mylib.h的方式,调用Myprintf函数实现功能。需要注意的是编译时注意加入mylib.o文件,因为编译时依赖这个文件
在这里插入图片描述
如上其实就是一个库的雏形,其本质就是这样的。之所以要打包为.a文件是因为.o文件太多了,所以方便管理

B:实现静态库

现在我要实现一个静态库,我的库主要提供两个功能:加法运算和减法运算

依次创建add.c add.h sub.c sub.h四个文件

在这里插入图片描述
四个文件内容如下

//add.h#include 
int add(int x,int y);//add.c#include "add.h”int add(int x,int y){
return x+y;}//sub.h#include
int sub(int x,int y);//add.c#include "sub.h"int sub(int x,int y){
return x-y;}

接着把所有的.c文件编译为对应的.o文件

在这里插入图片描述
好的,现在开始打包静态库。使用ar -rc命令(rc表示replace and creat),输入ar-r c libMYLIB.a add.o sub.o,表示将add.osub.o打包为libMYLIB.a
在这里插入图片描述

好的现在只需将头文件和.a文件交付给别人就可以使用了。所以要进行最后一次封装,创建一个目录 my_method,然后在该目录下分别创建两个目录:includelib,将.h文件拷贝至include目录下,将.a文件拷贝至lib目录下

在这里插入图片描述

好的,现在有一个程序test.c想要使用我的库

在这里插入图片描述

比如要使,库中的加法,那么就编写test.c如下

#include 
#include "add.h"int main(){
int x=10; int y=20; printf("%d\n",add(x,y)); return 0;}

然后编译,输入:gcc -static -o test.exe test.c -I./my_method/include -L./my_method/lib -lMYLIB 其中的一些选项解释如下

  • -I./my_method/include :告诉编译器去哪里寻找头文件
  • -L./my_method/lib:告诉编译器库在哪里
  • -lMYLIB:告诉编译器要使用哪个库(需要注意libMYLIB.a真正的库名是MYLIB

结果如下,编译成功,返回结果也是正确的

在这里插入图片描述

相应的减法也可以运行
在这里插入图片描述

C:实现动态库

讲完静态库之后,动态库就很好理解了。首先要将对应的.c文件编译为.o文件,编译时要加入-fPIC,表示产生位置无关码,打包时和静态有区别,打包动态库时还是使用gcc,同时加入-shared选项,表示生成共享库格式

这个过程稍显麻烦,所以使用Makefile一次性编写

libMYLIB.so:add.o sub.o	gcc -shared -o $@ $^add.o:add.c	gcc -fPIC -c add.csub.o:sub.c	gcc -fPIC -c sub.c.PHONY:cleanclean:	rm -rf *.o libMYLIB.so my_method.PHONY:packagepackage:	mkdir -p my_method/include	mkdir -p my_method/lib	cp *.h my_method/include	cp *.so my_method/lib

在这里插入图片描述

在这里插入图片描述

依然按照静态库的那个步骤,编译时不要加入-static选项:gcc -o test.exe test.c -I./my_method/include -L./my_method/lib -lMYLIB

编译成功
在这里插入图片描述
但是运行时却出现了错误:

在这里插入图片描述

这是因为,动态库和静态库不同,动态库在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入。所以编译器的确知道我们的库在哪,但是操作系统并不知道,所以要让操作系统知道这个路径才可以,使用ldd命令也可以发现这个问题
在这里插入图片描述
类比于环境变量PATH,操作系统也有这样的环境变量,以供操作系统搜索动态库:LD_LIBRARY_PATH。所以我们要把当前库的绝对路径导入到该环境变量之中。
在这里插入图片描述
自此,一切便正常运行了
在这里插入图片描述

转载地址:http://ojsi.baihongyu.com/

你可能感兴趣的文章