本文共 2151 字,大约阅读时间需要 7 分钟。
本文接:
前面说过,库其实就是头文件和和.a或.so文件的集合,而.a或.so文件则是由众多.o文件打包而成(不太准确)。所以只要有我的头文件和.o文件,使用者就可以使用我的代码了
如下我有两个文件一个是mylib.h,一个是mylib.c,目的是写一个自己的打印函数
代码如下 //mylib.h#includevoid 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文件太多了,所以方便管理 现在我要实现一个静态库,我的库主要提供两个功能:加法运算和减法运算
依次创建add.c add.h sub.c sub.h四个文件
四个文件内容如下 //add.h#includeint 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.o和sub.o打包为libMYLIB.a
好的现在只需将头文件和.a文件交付给别人就可以使用了。所以要进行最后一次封装,创建一个目录 my_method,然后在该目录下分别创建两个目录:include和lib,将.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文件编译为.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
但是运行时却出现了错误: 
类比于环境变量PATH,操作系统也有这样的环境变量,以供操作系统搜索动态库:LD_LIBRARY_PATH。所以我们要把当前库的绝对路径导入到该环境变量之中。
自此,一切便正常运行了
转载地址:http://ojsi.baihongyu.com/