【库函数】Linux下动态库.so和静态库.a的生成和使用

2024-06-18 1763阅读

【库函数】Linux下动态库.so和静态库.a的生成和使用

【库函数】Linux下动态库.so和静态库.a的生成和使用

目录

🌞1. Linux下静态库和动态库的基本概念

🌞2. 动态库

🌊2.1 动态库如何生成

🌍2.1.1 文件详情

🌍2.1.2 编译生成动态库

🌊2.2 动态库如何使用

🌍2.2.1 案例

🌍2.2.2 动态库错误记录

🌞3. 静态库

🌊3.1 静态库如何生成

🌍3.1.1 文件详情

🌍3.1.2 编译生成动态库

🌊3.2 静态库如何使用


🌞1. Linux下静态库和动态库的基本概念

库(Library)是一组预先编写好的程序代码,它们被打包在一起以供其他程序使用,从而避免了重复编写相同的代码。库可以分为静态库和动态库两种类型:

静态库

  • 作用:在程序编译的时候,将库编译进可执行程序中, 运行的时候不需要外部函数库
  • 目录:默认库目录 /lib 或 /usr/lib 或 /usr/local/lib
  • 后缀:libxxx.a
  • 命名规范:静态库的名字一般为libxxxx.a,其中 xxxx 是该lib的名称

    动态库

    • 作用:在程序运行的时候,将库加载到程序中,运行的时候需要外部函数库
    • 目录:默认的动态库搜索路径/lib;/usr/lib
    • 后缀:libxxx.so
    • 命名规范:动态库的名字一般为libxxxx.so.major.minor,xxxx 是该lib的名称,major是主版本号,minor是副版本号

      使用库的主要目的是:

      1. 提高代码的重用性和可维护性
      2. 减少开发人员的工作量
      3. 并使程序更加模块化和易于扩展

      常见的库包括:

      1. 标准库(如C标准库和C++标准库)
      2. 第三方库(如图形界面库、数据库访问库、网络通信库等)
      3. 自定义的库(根据项目需求编写的特定功能的库)

       对.h头文件的理解    传送门:【头文件】对.h文件的理解-CSDN博客


      🌞2. 动态库

      🌊2.1 动态库如何生成

      下面通过一个小栗子介绍如何生成一个动态库。

      1. 一个头文件:  so_test.h
      2. 头文件接口实现的三个c文件:so_test_a.c  so_test_b.c  so_test_c.c
      3. 我们将这几个文件编译成一个动态库:libtest.so

      🌍2.1.1 文件详情

      我在路径/root/host/my_program/asoc/include下创建四个文件

      一个头文件:

      vi so_test.h
      #ifndef SO_TEST_H
      #define SO_TEST_H
      int addTwoiNum(int a, int b);
      int subTwoiNum(int a, int b);
      int mulTwoiNum(int a, int b);
      #endif
      

      三个.c文件:

      vi so_test_a.c
      #include "so_test.h"
      #include 
      int addTwoiNum(int a, int b) {
          return a + b;
      }
      
      vi  so_test_b.c
      #include "so_test.h"
      #include 
      int subTwoiNum(int a, int b) {
          return a - b;
      }
      
      vi so_test_c.c
      #include "so_test.h"
      #include 
      int mulTwoiNum(int a, int b) {
          return a * b;
      }
      

      🌍2.1.2 编译生成动态库

      给文件附上权限:

      chmod 777 so_test_a.c so_test_b.c so_test_c.c so_test.h 

      【库函数】Linux下动态库.so和静态库.a的生成和使用

      接下来,我们将编译这些文件成一个动态库。

      在Linux系统中可以使用gcc来完成这个任务。

      gcc -c -Wall -Werror -fpic so_test_a.c  so_test_b.c  so_test_c.c
      gcc -shared -o libtest.so so_test_a.o so_test_b.o so_test_c.o
      

      第一行命令 :

      • -c 选项告诉编译器只编译源文件,而不进行链接。
      • -fpic 选项用于生成与位置无关的代码,这是动态链接库所必需的。

        第二行命令:

        • 使用 -shared 选项将目标文件链接成一个共享对象(动态库) libtest.so。

          现在,会得到一个名为 libtest.so 的动态库文件。

          【库函数】Linux下动态库.so和静态库.a的生成和使用


          🌊2.2 动态库如何使用

          前面已经成功生成了一个动态链接库libtest.so,下面通过一个程序来调用这个库里的函数。

          比如程序的源文件为:main.c【我创建的目录是/root/host/my_program/asoc/my_program】

          #include 
          #include "so_test.h"
          int main() {
              int result_a, result_b, result_c;
              int x = 10, y = 5;
              // 调用动态库中的函数
              result_a = addTwoiNum(x, y);
              result_b = subTwoiNum(x, y);
              result_c = mulTwoiNum(x, y);
              // 打印结果
              printf("Result of add: %d\n", result_a);
              printf("Result of sub: %d\n", result_b);
              printf("Result of mul: %d\n", result_c);
              return 0;
          }
          

          现在需要链接 libtest.so 到源文件。

          下面是编译模板:

          gcc -o main main.c -I/path/to/include -L/path/to/lib -ltest

          模板参数说明:

          • -o main:指定输出文件的名称为 main。
          • main.c:您的源文件。
          • -I/path/to/include:指定要搜索头文件的路径。
          • -L/path/to/lib:指定要搜索库文件的路径。
          • -ltest:指定要链接的库文件名称。这里假设动态库文件名为 libtest.so。

            请将 /path/to/include 和 /path/to/lib 替换为实际的路径。


            🌍2.2.1 案例

            【案例】如果头文件路径是 /root/host/my_program/asoc/include/so_test.h,动态库文件路径是 /root/host/my_program/asoc/include/libtest.so,可以这样编译 main.c 文件:

            gcc -o main main.c -I/root/host/my_program/asoc/include -L/root/host/my_program/asoc/include -ltest

            在这个命令中:

            • -o main:指定输出文件的名称为 main。
            • main.c:源文件。
            • -I/root/host/my_program/asoc/include:指定要搜索头文件的路径。
            • -L/root/host/my_program/asoc/include:指定要搜索库文件的路径。
            • -ltest:指定要链接的库文件名称。

              链接完成会生成一个 main 的可执行文件,这个可执行文件到底有没有成功链接到动态链接库呢?

              可以使用下面的命令来查看:

              ldd main

              【库函数】Linux下动态库.so和静态库.a的生成和使用

              这里说明虽然我们已经使用 -L 选项指定了库文件的搜索路径,但是系统加载器在搜索动态库时还是会按照默认的路径 /lib  或者 /usr/lib 的路径进行搜索,因此即使编译成功,但运行时仍找不到动态库。

              要解决这个问题,可以尝试设置 LD_LIBRARY_PATH 环境变量来指定动态库的搜索路径。例如我的动态库.so是在路径/root/host/my_program/asoc/include下,则使用命令:

              LD_LIBRARY_PATH=/root/host/my_program/asoc/include ./main

              【库函数】Linux下动态库.so和静态库.a的生成和使用

              这样运行时就能够找到动态库 libtest.so+运行成功!


              🌍2.2.2 动态库错误记录

              这个错误是在动态库执行的时候经常会遇到,说找不到这个.so文件,如果放在/lib或者/usr/lib下,那么默认就能找到。如果放在其他目录下,有 3 种解决方案:

              1. 将.so 文件拷贝到 /usr/lib/文件夹下面
              2. 添加PATH环境变量【前面的案例就是使用这个解决】

                export LD_LIBRARY_PATH=

              3. 修改配置脚本

                将动态库所在的路径加到  /etc/ld.so.conf 文件里

                vim /etc/ld.so.conf
                添加后刷新
                /sbin/ldconfig

              🌞3. 静态库

              🌊3.1 静态库如何生成

              下面通过一个小栗子介绍如何生成一个静态库。

              1. 一个头文件:  vi staticlib.h
              2. 头文件接口实现的三个c文件:staticlib.c
              3. 我们将这几个文件编译成一个静态库:libstatic.a

              🌍3.1.1 文件详情

              我在路径/root/host/my_program/asoc/include下创建下面的文件

              vi staticlib.h
              #ifndef __STATICLIB_H
              #define __STATICLIB_H
              int hello();
              #endif
              vi staticlib.c
              #include "staticlib.h"
              #include 
              int hello(){
                  printf("hello,this is static lib\n");  
                  return 0;
              }

              🌍3.1.2 编译生成动态库

              给文件附上权限:

              chmod 777 staticlib.h staticlib.c

              使用编译器将 staticlib.c 编译成目标文件(.o 文件):

              gcc -c staticlib.c -o staticlib.o

              使用 ar 命令将目标文件打包成静态库文件 libstatic.a:

              ar rcs libstatic.a staticlib.o

              这样就生成了名为 libstatic.a 的静态库文件,其中包含了 staticlib.o 的内容。

              【库函数】Linux下动态库.so和静态库.a的生成和使用


              🌊3.2 静态库如何使用

              前面已经成功生成了一个动态链接库libtest.so,下面通过一个程序来调用这个库里的函数。

              比如程序的源文件为:test.c【我创建的目录是/root/host/my_program/asoc/my_program】

              内容如下:

              #include 
              #include "staticlib.h"
              int main() {
                  printf("Calling hello() function...\n");
                  hello();
                  return 0;
              }
              

              接下来,需要编译 main.c 并链接静态库 libstatic.a。

              gcc test.c -o test -I/root/host/my_program/asoc/include/ -L/root/host/my_program/asoc/include/ -lstatic
              

              参数说明:

              •  -L 参数指定了编译器搜索库文件的路径
              • -lstatic 指定了要链接的静态库名字(注意,lib 前缀和 .a 扩展名都不需要在此处指定)

                然后运行可执行文件 test:

                ./test

                【库函数】Linux下动态库.so和静态库.a的生成和使用

                说明静态库链接成功!

                【库函数】Linux下动态库.so和静态库.a的生成和使用

                【库函数】Linux下动态库.so和静态库.a的生成和使用

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]