Linux环境下静态库和动态库的使用讲解,linux静态


1. 库的引入

c/c++项目的源码文件的组成一般为.c/.cpp和.h文件,可能你写的函数要供其他人使用,但你不能把你写的源码提供给别人,库就很好的解决了这个问题。gcc的-c编译选项可以将c/c++源文件只编译不链接,即生成.o文件。.o文件和.c/.cpp文件实际上都是源代码文件,只是前者是二进制格式的(人眼无法识别器内容),后者是文本格式的(人眼可以识别其内容),对于计算机来说前者后者并无差别,都能正确识别。我们将这些.o文件打包,即可形成一个源码无法被识别的库文件。

用户无法识别库文件的代码,那如何使用库文件 中的函数?这就需要头文件。因此.h文件是不需要生成二进制格式后提交给用户的,用户根据.h文件中的函数声明就可以正确使用库文件中的函数。

2. 静态库

2.1 命名规则

Linux环境下静态库的命名由前缀、名称、后缀组成,以libtest.a为例:

(1)前缀(固定的):lib

(2)名称(自定义的):test

(3)后缀(固定的):.a

2.2 静态库的制作

(1)将.c/.cpp文件生成.o文件

gcc -c a.c b.c

(2)将.o文件打包
ar rcs 静态库的名称 .o文件

ar rcs libtest.a a.o b.o

举例,将用于实现四则运算的.c文件打包成libmycalc.a文件:

//include/calc.h
#ifndef __CALA_H__
#define __CALA_H__

int add(int a, int b);
int sub(int a, int b);
int mul(int a, int b);
int p(int a, int b);

#endif /* __CALA_H__ */

//src/add.c
#include "calc.h"

int add(int a, int b)
{
    return a + b;   
}

//src/p.c
#include "calc.h"

int p(int a, int b)
{
    return a / b;
}

//src/mul.c
#include "calc.h"

int mul(int a, int b)
{
    return a * b;
}

//src/sub.c
#include "calc.h"

int sub(int a, int b)
{
    return a - b;   
}

这里写图片描述

(-I指定头文件的路径)

2.3 静态库的使用

//main.c
#include 
#include "calc.h"

int main(void)
{
    printf("%d\n", add(4, 6));  
    return 0;
}

这里写图片描述

(-L指定库的路径,-l指定库的名称(去除前缀和后缀))

3. 动态库

3.1 命名规则

Linux环境下动态库的命名依旧由前缀、名称、后缀组成,以libtest.so为例(有的动态库名称还包含版本信息,如libtest.so.10.0.0):

(1)前缀(固定的):lib

(2)名称(自定义的):test

(3)后缀(固定的):.so

3.2 动态库的制作

(1)将.c/.cpp文件生成.o文件

gcc -c a.c b.c -fpic    //-fpic也可写成-fPIC

(2)打包

gcc -shared -o libtest.so a.o b.o

还是以前面的代码为例:

这里写图片描述

3.3 动态库的使用

跟使用静态库的使用方法一样:

这里写图片描述

运行a.out时提示找不到libmycalc.so动态库。这是因为:当系统加载可执行代码时,除了需要知道程序所依赖的库的名字,还需要知道该库的绝对路径。前者是通过gcc编译命令选项指定的,后者则是需要系统动态加载器完成。通过ldd命令可查看elf可执行程序所依赖的库:

这里写图片描述

/lib/ld-linux.so.2即为系统动态加载器。elf格式的可执行程序是由ld-linux.so*来完成的,它先后搜索:

(1)elf文件的DT_RPATH段

(2)环境变量LD_LIBRARY_PATH

(3)/etc/ld.so.cache文件列表

(4)/lib/或/usr/lib目录

为了让加载器找到动态库,我们可以:

(1)拷贝自己制作的libmycalc.so到/lib/或/usr/lib中

(2)临时设置环境变量LD_LIBRARY_PATH

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库的路径

“$LD_LIBRARY_PATH:库的路径”表示在原先的LD_LIBRARY_PATH的值上增加库的路径。

(3)永久设置环境变量LD_LIBRARY_PATH

a. 用户级别

在~/.bashrc文件中增加动态库的搜索的绝对路径

这里写图片描述

配置完成后需要重启终端或者执行命令:

source ~/.bashrc
或者 .~/.bashrc

b. 系统级别

将上述路径增加至/etc/profile,配置完毕后需要重启系统或执行命令:

source /etc/profile
或者 . /etc/profile

(4)更新/etc/ld.so.cache文件列表

把动态库的绝对路径添加到配置文件/etc/ld.so.conf中,然后执行命令:

sudo ldconfig -v

相关内容