Linux C中动态链接库的使用

动态链接库可以简单这么理解:

有两个工程:

  • 【工程1】专门用来生成.so链接库文件,生成库以后只需要保留libxxx.so库文件即可,其他文件均可以不需要。
  • 【工程2】为实际项目工程,需要使用上面的so库。

下面以一个简单的加减乘除demo为例记录生成、使用动态链接库的方法。


1、工程1:生成动态链接库【libcaculate.so】

生成链接库的代码实际上跟最后工程的代码没有关系,该步骤的目的仅仅是生成动态链接库,之后将so库文件和接口声明.h文件提供给别人,别人就可以使用了。

1.1 代码

  • 工程目录结构:

    code_delivery_lib_so
        ├── caculate.c
        ├── caculate.h
        └── Readme.txt
    
  • caculate.c

    #include <stdio.h>
    #include <string.h>
    
    //加法
    int add(int a, int b) {
        return ((a) + (b));
    }
    
    //减法
    int sub(int a, int b) {
        return ((a) - (b));
    }
    
    //除法
    int div(int a, int b) {
        return (int)((a) / (b));
    }
    
    //乘法
    int mul(int a, int b) {
        return ((a) * (b));
    }
    
  • caculate.h

    该文件作为so库对外接口函数声明文件,里面包含了库中所有可供调用的函数声明。

    备注:事实上该文件作为对外接口声明文件,代码结构中是可有可无的。其本质意义其实更像是一个Readme文件,告诉使用so库的人:我都给你提供了什么函数。你要用哪些函数,你就新建一个.h文件,声明一下这些函数,或者直接用我这个.h文件。

    #ifndef CACULATE_H
    #define CACULATE_H
    
    //加法
    int add(int a, int b);
    //减法
    int sub(int a, int b);
    //除法
    int div(int a, int b);
    //乘法
    int mul(int a, int b);
    
    #endif
    
  • Readme.txt

    生成动态链接库命令:
        gcc -shared -fPIC caculate.c -o libcaculate.so
        
    其中:
        -shared -fPIC    参数指明要生成链接库文件
        -o               参数指定生成的链接库的名称
    注意:
        libcaculate.so   固定格式链接库名称为:libxxx.so,前缀lib,后缀.so,系统会自动识别名称xxx
                         本例子中,库名称为caculate,使用链接库命令的时候会用该名称
    

## 1.2 终端执行命令

  • gcc -shared -fPIC caculate.c -o libcaculate.so
    

    可以看到当前文件夹下生成了一个libcaculate.so文件。

    项目开发时,提供给别人【libcaculate.so】和【caculate.h】文件就可以了。

2、工程2:项目工程(使用动态链接库)

2.1 代码

  • 工程目录结构:

    project
        ├── lib
        │   ├── caculate.h
        │   └── libcaculate.so
        ├── main.c
        └── Readme.txt
    
  • caculate.h

    该文件作用是声明so库文件中可调用的函数。没有该文件的话,编译会报错。

    #ifndef CACULATE_H
    #define CACULATE_H
    
    //加法
    int add(int a, int b);
    //减法
    int sub(int a, int b);
    //除法
    int div(int a, int b);
    //乘法
    int mul(int a, int b);
    
    #endif
    
  • main.c

    #include <stdio.h>
    #include <string.h>
    #include "./lib/caculate.h"  //引用对应库的头文件,注意路径
    
    int main(int argc, char *argv[]) {
        int a = 5;
        int b = 8;
    
        printf("a + b = %d\r\n", add(a, b));
        printf("a - b = %d\r\n", sub(a, b));
        printf("a * b = %d\r\n", mul(a, b));
        printf("a / b = %d\r\n", div(a, b));
    
        return 0;
    }
    
  • Readme.txt

    使用动态链接库命令:
        gcc main.c -o main -L ./lib/ -lcaculate  -Wl,-rpath,$(pwd)/lib/
    
    其中:
        -L          指定链接库的路径
        -l          后面跟链接库的名称,要省略前缀lib和后缀.so,编译器会自动解析加上前后缀的
        -Wl,-rpath  指定环境变量库路径,$(pwd)/lib/表示当前目录下的lib目录
    

2.2 终端执行命令

  • gcc main.c -o main.out -L ./lib/ -lcaculate  -Wl,-rpath,$(pwd)/lib/
    

    可以看到目录下生成一个可执行文件【main.out】

2.3 结果展示

  • 执行main.out

    lsy@ubuntu18:~/practice/c/lib_so_test/test/project$ ./main.out 
    a + b = 13
    a - b = -3
    a * b = 40
    a / b = 0
    

3、学习动态链接库时遇到的坑

3.1 接口声明文件xxx.h

我们要用库文件中的函数,我们就需要自己新建一个xxx.h文件声明这些函数,或者直接copy一份提供so库文件的人员给我们提供的.h文件。然后再对应.c文件中加上头文件引用:#include “xxx.h”。最后进行工程编译。

否则会报错函数未定义,或者找不到xxx.h文件。

简单概括,步骤如下:

使用so库,代码注意事项步骤:

  • 拿到so库
  • 写一个xxx.h文件,声明我们即将调用的函数(或者可以直接使用提供.so库人员给我们的.h声明文件)
  • 对应.c文件中加上头文件引用:#include “xxx.h”

3.2 环境变量LD_LIBRARY_PATH的设置

有时候链接库的时候,会提示找不到库,报错,因为系统环境变量会默认找LD_LIBRARY_PATH所指向的路径,此时可以临时这是环境变量LD_LIBRARY_PATH的值,也可以将libxxx.so拖到usr/lib下面,也可以用另一种方法,即编译命令中直接加上参数,指定库路径,这样写Makefile的时候也会非常方便。

即:

使用动态链接库命令:
    gcc main.c -o main -L ./lib/ -lcaculate  -Wl,-rpath,$(pwd)/lib/

中的-Wl,-rpath 这两个参数,具体含义如下:

    -Wl,-rpath  指定环境变量库路径,$(pwd)/lib/表示当前目录下的lib目录
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值