制作步骤:

  1. 编译得到 .o 可链接目标文件
  2. .o 打包为 .a 静态库文件(归档文件archive)

使用步骤:

  1. 编写自己的 .c 文件源代码
  2. 链接静态库:比如C文件名称是main.c,动态库文件名为 libmycaculate.a
    注意:此时 -L 是编译链接用的,与静态库加载运行无关
    gcc main.c -o main -L./static_lib -lcaculate -I./static_lib
    
  3. 静态库,相当于把库文件内容直接复制到我们的项目文件中,所以链接后可以直接运行了

-L:指定静态库所在的路径(路径为./static_lib),链接时会到该路径下去查寻找静态库
-l:指定库的名字,指定库名字时需要将前缀lib和后缀.a省略,指向到静态库文件libcaculate.a
-I:指定caculat.h所在的路径,路径为./static_lib


一、静态库制作

制作为静态库的代码:

代码实现add/sub/mul/div/power等算数运算函数,然后做成静态库,
在我们的程序中链接了这个静态库之后,我们就可以调用这些函数来进行算数运算了

代码文件:

  • caculate.h:头文件,存放库函数的声明
  • add_sub.c:加法、减法
  • mul_div.c:乘法、除法、平方

1. 源码文件:

文件:caculate.h

#ifndef H_CACULATE_H
#define H_CACULATE_H

extern double add(double arg1, double arg2);
extern double sub(double arg1, double arg2);
extern double mul(double arg1, double arg2);
extern double div(double arg1, double arg2);
extern double power(double arg);

#endif

文件:add_sub.c

#include "caculate.h"

double add(double arg1, double arg2)
{
    double sum = 0;

    sum = arg1 + arg2;

    return sum;
}

double sub(double arg1, double arg2)
{
    double sum = 0;

    sum = arg1 - arg2;

    return sum;
}

文件:mul_div.c

#include "caculate.h"

double power(double arg)
{
    double sum = 0;

    sum = mul(arg, arg);

    return sum;
}

double mul(double arg1, double arg2)
{
    double sum = 0;

    sum = arg1 * arg2;

    return sum;
}

double div(double arg1, double arg2)
{
    double sum = 0;

    sum = arg1 / arg2;

    return sum;
}

2. 将源码制作为静态库文件

1)得到.o文件

gcc -c add_sub.c -o add_sub.o
gcc -c mul_div.c -o mul_div.o

2)将.o文件打包为静态库文件

ar  -crv  ./libcaculate.a  add_sub.o  mul_div.o
  • (a)ar:打包命令
  • (a)-crv:显示打包过程
  • (b)./libcaculate.a:静态库的路径名

静态库的完整名字,前缀lib和后缀.a为固定格式,中间的caculate才是真正的静态库的名字。

file命令查看时,会告诉你静态库文件其实是一个归档文件

ar命令其实“归档命令”,专门用来实现对文件进行归档,所以说制作静态库文件其实就是制作一个归档文件

归档文件和压缩文件很相似,只不过归档文件只打包不压缩,但是压缩文件不仅会打包,而且还会进行压缩


二、使用静态库

1. 写一个调用库函数的 main.c

#include <stdio.h>
#include "./static_lib/caculate.h"  //包含静态库的头文件

int main(void)
{
    double a = 10.5;
    double b = 20.6;
    double ret = 0;

    ret = add(a, b); //加
    printf("add: ret = %f\n", ret);

    ret = sub(a, b); //减
    printf("sub: ret = %f\n", ret);

    ret = mul(a, b); //乘
    printf("mul: ret = %f\n", ret);
    ret = div(a, b);
    printf("div: ret = %f\n", ret);

    ret = power(a);  //除
    printf("power: ret = %f\n", ret);

    return 0;
}

包含静态库的头文件时,如果caculate.h不在当前路径时怎么办,

  • 可以在””中指定.h所在的路径
  • gcc时通过-I选项,将.h所在路径加入”头文件系统路径”

有关“头文件”的相关内容,我们在第二章有非常详细的介绍,不清楚的同学,请看这一章
C高级 - include 包含文件

2. 编译 main.c 并 链接 静态库

(a)如果不链接静态库会怎样

/tmp/ccTCMbDN.o: In function `main':
main.c:(.text+0x42): undefined reference to `add'
main.c:(.text+0x82): undefined reference to `sub'
main.c:(.text+0xc2): undefined reference to `mul'
main.c:(.text+0x139): undefined reference to `power'
collect2: error: ld returned 1 exit status

报一堆的链接错误,提示链接时找不到这些函数的定义

当你在调用某个函数时如果把函数名写错了,同样也会提示你找不到函数的定义的错误,
因为而错误的函数名肯定没有对应任何的函数定义,自然会报错

在我们这里并没有把名字写错,而是没有链接定义这些函数静态库,所以找不到函数的定义

(b)链接静态库

gcc main.c -o main -L./static_lib -lcaculate -I./static_lib

-L:指定静态库所在的路径(路径为./static_lib),链接时会到该路径下去查寻找静态库
-l:指定库的名字,指定库名字时需要将前缀lib和后缀.a省略,指向到静态库文件libcaculate.a
-I:指定caculat.h所在的路径,路径为./static_lib

其实有关-l,我们在第一章介绍gcc -v详细信息就提到过
C高级 - gcc -v 详细信息解读,启动代码

疑问:能不能省略静态库的路径?

答:可以
只要将所在路径加入了环境变量,链接时会指定到该路径下寻找静态库,此时我们不用自己指定静态库所在的路径

疑问:如何将路径加入环境变量呢?

答:我们在《Linux系统编、程网络编程》课程的第四章——进程环境中有详细介绍