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


    静态库的用法

    静态库的文件名 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
    ",add(a, b));
      printf("sub:%d
    ",sub(a, b));
      printf("mul:%d
    ",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后,就记录了每个函数相对于这个动态库头地址的偏移,加载后动态库在内存里的头地址是知道的,又知道了每个函数相对于头的偏移量,自然而然地就能够找到每个函数在内存里的位置了。

    做静态库的命令(-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/
    

    结果如下:

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

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

    结果如下:

    发现软连接是绿色的了,说明库可以使用了,开森啊。
    再用【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了。

    静态库和动态库的特点:

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

    c/c++ 学习互助QQ群:877684253

    本人微信:xiaoshitou5854

  • 相关阅读:
    【Vim】多文件操作
    TC(Traffic Control)命令—linux自带高级流控
    【ceph | 运维】亲和性
    【Vim】Vim分屏基本操作
    Dubbo常用功能06集群容错
    Dubbo负载均衡策略轮询
    Redis知识体系
    Dubbo常用功能09参数回调
    Dubbo负载均衡策略最少活跃调用数
    Dubbo常用功能10异步调用
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/10750141.html
Copyright © 2020-2023  润新知