zoukankan      html  css  js  c++  java
  • 一文教你如何构建自己的函数库

    话说ISOC99有自己的一系列标准C函数库,例如我们熟悉的libc.a(包含标准I/O函数、字符串操作函数和整数数学函数)和libm.a(浮点数数学函数),可供我们在使用gcc编译工具编译程序时调用。那么,如果我们在日常学习或项目开发中积累了许多好的函数,希望日后在其他项目中能够复用时,我们又该如何去保存他们呢?今天我就告诉大家怎么办?

    1. 看gcc编译器都干了些什么?

    所谓,知己知彼,百战不殆。
    首先,用一个例子带大家了解一下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观察到工作过程。
    看图☞

    6217760-cb5628b6a23432f5.jpg
    静态链接

    1.1 cpp预处理

    cpp main.c -o main.i
    

    预处理器cpp将源代码main.c翻译成一个ASCII码的中间文件main.i。

    1.2 ccl编译

    ccl -Og main.i -o main.s
    

    C编译器ccl将中间文件翻译成一个ASCII码的汇编语言文件main.s。
    备注:-O参数选择优化级别,由低到高分别为g<1<2<3。一般g和1优化级别用于调试阶段,2和3用于最后交付前的优化阶段。

    1.3 as汇编

    as main.s -o main.o
    

    汇编器as将汇编文件翻译成一个二进制的可重定位的目标文件main.o。

    1.4处理其他源文件

    经过相同的步骤,将另一个源文件sum.c转换成sum.o

    1.5 ld链接

    ld -o prog main.o sum.o
    

    1.6 加载运行

    以上步骤都做完之后,最后在命令行(shell)键入./prog就可以运行啦。shell会调用操作系统中一个叫加载器的函数,它将可执行文件中的代码和数据复制到内存,然后将控制权交给该程序。

    2. 创建自己的函数库

    假设在某个项目中你自己编写了两个函数addvec() 和mulvec(),感觉很牛逼很好用,希望以后在其他项目里也能用的上。这里有两种方法,一是保存他们的源代码,以后编写程序时插进去;二是将他们加入到一个自己的私有库中,在使用时可在其他文件中直接调用。

    前者or后者哪个方便?

    如果你选择前者,好的你可以结束阅读课,选择后者,请继续往下看:

    2.1 制作目标文件

    gcc -c myfuncs.c 
    

    将包含你所需要打包的函数的c文件编译成可重定位的目标文件

    2.2生成静态库

    ar rcs libmyfuncs.a myfuncs.o
    

    利用AR库制作工具,创建我们所需的静态库。

    2.3 制作.h头文件

    新建一个头文件myfuncs.h,要求其中包含所有myfuncs.a库中函数的原型语句。

    3. 使用方法

    假设我们在示例程序example.c中需要使用静态库myfuncs.a中的函数。我们该怎么办呢?

    3.1 添加头文件;

    将头文件myfuncs.h添加到自己的工程目录中,并在example.c文件的顶端添加#include "myfuncs.h"语句,之后就可以使用库中的函数了。

    3.2 编译选项

    当你的程序example.c编写完毕后,在编译阶段链接我们的自定义库。

    gcc -c example.c
    
    gcc -static -o prog example.o -L. -lmyfuncs
    

    第一条语句用来生成目标文件example.o
    第二条语句中,-static参数告诉连接器应该构建一个完全链接的可执行目标文件,它可以直接加载到内存并运行,且在加载时无需再做其他链接。-L告诉链接器应该在当前目录下查找库(因为L后面跟的是一个点,而点在linux系统中代表当前目录)。-l后面直接跟你需要链接的库的名字的缩写myfuncs,而不是全称libmyfuncs.a。

    注意:链接器还会默认链接C标准函数库libc.a。

    获取更多知识,请点击关注:
    嵌入式Linux&ARM
    CSDN博客
    简书博客

  • 相关阅读:
    uva 408 Uniform Generator
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 不同单词个数统计
    Java实现 蓝桥杯VIP 算法提高 不同单词个数统计
  • 原文地址:https://www.cnblogs.com/leon1124/p/14039690.html
Copyright © 2011-2022 走看看