C/C++ 动态库与静态库的制作和使用

栏目: C++ · 发布时间: 5年前

内容简介:静态库的文件名 libxxx.a -->对应Windows的.lib文件注意:-L的作用是告诉gcc你的libxxx.a放在了哪个目录里;-l的作用是告诉gcc使用哪个静态库。head.h

静态库的用法

静态库的文件名 libxxx.a -->对应Windows的.lib文件

做静态库的命令:

ar rcs libxxx.a file1.o file2.o file.o

使用静态库:

gcc main.c -L lib/ -lxxx

注意:-L的作用是告诉gcc你的libxxx.a放在了哪个目录里;-l的作用是告诉gcc使用哪个静态库。

举个例子,目录结果如下:

├── include
│   └── head.h
├── lib
│   
├── main.c
└── src
    ├── add.c
    ├── mul.c
    └── sub.c

head.h

int add(int, int);
int sub(int, int);
int mul(int, int);

add.c

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

sub.c

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

mul.c

int mul(int a, int b){
  return a * b;
}
  • 步骤1:在src目录执行下面的命令,生产.o文件
gcc -c *.c

执行后,在src目录下生产了add.o,sub.o,mul.o三个文件

  • 步骤2:在src目录执行下面的命令,生产libCalc.a文件
ar rcs libCalc.a *.o

执行后,在src目录下生产了libCalc.a

  • 步骤3:在src目录执行下面的命令,把libCalc.a移动到上层的lib文件夹
mv libCalc.a ../lib/

执行后,在lib文件夹出现了libCalc.a

main.c

#include <stdio.h>
#include "head.h"

int main(){
  int a = 10, b = 5;
  printf("add:%d\n",add(a, b));
  printf("sub:%d\n",sub(a, b));
  printf("mul:%d\n",mul(a, b));
}
  • 步骤4:在src的上层目录,执行下面命令生产a.out文件
gcc main.c -I include/ -L lib/ -lCalc
  • -I:指定头文件所在的路径

  • -L:指定静态库文件所在的路径
  • -l:指定使用哪个静态库

最后目录结构如下:

├── a.out
├── include
│   └── head.h
├── lib
│   └── libCalc.a
├── main.c
└── src
    ├── add.c
    ├── add.o
    ├── mul.c
    ├── mul.o
    ├── sub.c
    └── sub.o

动态库的用法

动态库的文件名 libxxx.so -->对应windows的.dll文件

编译时,需要加【-fPIC】选项。

它的作用是,编译出与位置无关的代码。因为动态库在加载到下图的共享库区的时候,不一定加载到哪个位置,

所以加了-fPIC后,就记录了每个函数相对于这个动态库头地址的偏移,加载后动态库在内存里的头地址是知道的,又知道了每个函数相对于头的偏移量,自然而然地就能够找到每个函数在内存里的位置了。

C/C++ 动态库与静态库的制作和使用

做静态库的命令(-shared):

gcc -shared -o libCalc.so *.o

用【ldd】命令查看编译出来的可执行文件文件

ldd a.out

结果如下:

ys@ys-VirtualBox:~/lianxi1$ ldd a.out 
    linux-vdso.so.1 (0x00007ffdebd2d000)
    libCalc.so => not found
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3b3e7ee000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f3b3ede1000)

发现【libCalc.so => not found】

解决办法1:把做好的动态库libCalc.so拷贝到【/lib】或者【/usr/lib】下,也可以用ln做软硬连接:把当前目录下的lib目录下的libCalc.so链接到/lib下

sudo ln -s ./lib/libCalc.so /lib/

结果如下:

C/C++ 动态库与静态库的制作和使用

发现软连接是红色的,也就是不能使用的意思,错误在于./lib/libCalc.so这个路径是不存在的,原因在于上面的命令使用的是相对路径,改成绝对路径就OK了,命令如下:

sudo ln -s ~/lianxi1/lib/libCalc.so /lib/

结果如下:

C/C++ 动态库与静态库的制作和使用

发现软连接是绿色的了,说明库可以使用了,开森啊。

再用【ldd】命令查看编译出来的可执行文件文件

ldd a.out

结果如下:

ys@ys-VirtualBox:~/lianxi1$ ldd a.out 
    linux-vdso.so.1 (0x00007ffe783c4000)
    libCalc.so => /lib/libCalc.so (0x00007f35fd6ae000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f35fd2bd000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f35fdab2000)

发现【libCalc.so】已经被找到了,好开心。

但是这种方法不推荐使用。理由是,放在了系统的动态库目录里,容易和别的库重复,发生冲突。

解决办法2:告诉系统,给我加一个动态库的路径,这个是最好的办法。

  • 首先编辑/etc/ld.so.conf文件,添加你自己的库的路径
  • 然后,执行:【sudo ldconfig】,就OK了。

静态库和动态库的特点:

  • 静态库:
    • 编译的时候,直接把静态库的代码直接编译到目标文件
    • 执行速度快,不需要在执行的时候加载动态库
    • 库文件修改后,必须重新编译使用库的代码
  • 动态库
    • 编译的时候,不把静态库的代码直接编译到目标文件
    • 执行速度慢,在执行的时候需要加载动态库
    • 库文件修改后,一般不需要重新编译使用库的代码,只有在库的接口改变时,才需要重新编译使用库的代码。

Linux公社的RSS地址https://www.linuxidc.com/rssFeed.aspx

本文永久更新链接地址: https://www.linuxidc.com/Linux/2019-04/158302.htm


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

概率论基础教程

概率论基础教程

罗斯 / 赵选民 / 机械工业出版社 / 2006-4 / 42.00元

本书是一本概率论的入门教材,系统介绍了概率论的基础理论及应用,在取材、结构和写作方法等方面具有鲜明的特点。通过例题阐述概率论的基本概念与方法是本书的一大特色。作者独具匠心地选择和编排了大量例题与习题,这些内容约占全书的三分之二。通过这些例题和习题,读者可以了解概率论在各个领域的广泛应用,如基因、彩票、法庭判决、NBA选秀等。   本书系统介绍了概率论的基础理论及应用,主要内容包括组合......一起来看看 《概率论基础教程》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具