本篇内容介绍了“怎么构建自己的函数库”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
所谓,知己知彼,百战不殆。
首先,用一个例子带大家了解一下gcc的编译过程。
//main.c int sum (int *a, int n); int array[2] = {1, 2}; int main() { int val = sum(array, 2); return val; }
//sum.c int sum(int *a, int n) { int i, s = 0; for(i=0; i < n; i++){ s += a[i]; } return s; }
假如一个项目共有以上2个源程序组成。main函数初始化一个整数数组,然后调用一个定义在另一个文件中的sum函数来对数组元素求和。
一般,我们会直接在命令行下键入gcc -Og -o prog main.c sum.c
来直接编译出二进制的可执行的ELF格式的目标文件prog。那在此之间,gcc到底都干了些什么工作呢?
(备注:可以在gcc命令中添加参数-v观察到工作过程。)
看图☞
静态链接
cpp main.c -o main.i
预处理器cpp将源代码main.c翻译成一个ASCII码的中间文件main.i。
ccl -Og main.i -o main.s
C编译器ccl将中间文件翻译成一个ASCII码的汇编语言文件main.s。
备注:-O参数选择优化级别,由低到高分别为g<1<2<3。一般g和1优化级别用于调试阶段,2和3用于最后交付前的优化阶段。
as main.s -o main.o
汇编器as将汇编文件翻译成一个二进制的可重定位的目标文件main.o。
经过相同的步骤,将另一个源文件sum.c转换成sum.o
ld -o prog main.o sum.o
以上步骤都做完之后,最后在命令行(shell)键入./prog
就可以运行啦。shell会调用操作系统中一个叫加载器的函数,它将可执行文件中的代码和数据复制到内存,然后将控制权交给该程序。
假设在某个项目中你自己编写了两个函数addvec() 和mulvec(),感觉很牛逼很好用,希望以后在其他项目里也能用的上。这里有两种方法,一是保存他们的源代码,以后编写程序时插进去;二是将他们加入到一个自己的私有库中,在使用时可在其他文件中直接调用。
前者or后者哪个方便?
如果你选择前者,好的你可以结束阅读课,选择后者,请继续往下看:
gcc -c myfuncs.c
将包含你所需要打包的函数的c文件编译成可重定位的目标文件
ar rcs libmyfuncs.a myfuncs.o
利用AR库制作工具,创建我们所需的静态库。
新建一个头文件myfuncs.h,要求其中包含所有myfuncs.a库中函数的原型语句。
假设我们在示例程序example.c中需要使用静态库myfuncs.a中的函数。我们该怎么办呢?
将头文件myfuncs.h添加到自己的工程目录中,并在example.c文件的顶端添加#include "myfuncs.h"
语句,之后就可以使用库中的函数了。
当你的程序example.c编写完毕后,在编译阶段链接我们的自定义库。
gcc -c example.c gcc -static -o prog example.o -L. -lmyfuncs
第一条语句用来生成目标文件example.o
第二条语句中,-static参数告诉连接器应该构建一个完全链接的可执行目标文件,它可以直接加载到内存并运行,且在加载时无需再做其他链接。-L告诉链接器应该在当前目录下查找库(因为L后面跟的是一个点,而点在linux系统中代表当前目录)。-l后面直接跟你需要链接的库的名字的缩写myfuncs,而不是全称libmyfuncs.a。
“怎么构建自己的函数库”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。