动态链接库(Unix/Linux)实战入门

本文介绍Unix/Linux环境下怎么使用命令行生成动态链接库,怎么链接动态链接库。
本文的代码在macOS环境下一一测试过。

生成动态链接库

如果用C

calculate.c

extern int g_Ver = 2;

int add(int a, int b) // extern can be ignore
{
    return a + b;
}

如果用C++,需要extern "C",因为目前动态链接库目前只支持C的接口。如果想导入类,也只能通过Factory函数来实现。

calculate.cpp

extern "C"
{
    extern int g_Ver = 2;// also can be declared as `extern "C" int g_Ver = 2;`
}
extern "C" int add(int a, int b)
{
    return a + b;
}

在linux环境下调用如下指令生成动态链接库:

$ gcc -shared calculate.c -o libcalculate.so

在macOS环境下也可以用如下指令生成动态链接库:

$ gcc -dynamiclib calculate.c -o libcalculate.so

C++也是一样的指令。

使用nm可以查看动态库的详情:

$ nm libcalculate.so

动态链接库和静态库的区别

静态链接库的本质是目标文件的集合,一般使用如下方式生成静态库

$ gcc -c calculate.c # generates calculate.o
$ ar rc libcalculate.a calculate.o # use `ar` to pack the static library

需要注意,如果当前已经有libcalculate.a,那么ar rc可能生成失败,可以先删除lib。

静态库生成的过程不涉及链接,只是一堆目标文件的集合,而动态链接库需要把代码中涉及到的外部函数和变量链接到位,才能生成成功。这是静态库和动态链接库的区别。

链接动态链接库

首先编写如下编码,以下为C语言版本

main.c

#include "stdio.h"

extern int add(int a, int b);
extern int g_Ver;

int main()
{
    printf("%d\n", add(5, 5));
    printf("%d\n", g_Ver);
    return 0;
}

这个代码可以用来跟静态库链接,也可以跟动态链接库进行运行时隐式链接(dynamic linking)。

使用如下指令进行动态库链接:

$ gcc -rdynamic main.c -o main -lcalculate -L.

去掉-rdynamic即为静态链接的方式。

虽然动态链接时不会把动态链接库加载进执行文件,但依旧会检查隐式链接的接口是否在动态库中实现。

C++的版本同理,需要在声明中添加extern "C"

如果想要使用显式链接的模式(dynamic loading),需要编写如下的代码:

#include "stdio.h"
#include "dlfcn.h"

typedef int (*Func)(int a, int b);

int main()
{
    void* pdlhandle = dlopen("./libcalculate.so", RTLD_LAZY);
    char* pszerror; 
    Func mytest;
    int * p_Ver;
    if (0 != pszerror)  {
        printf("%s\n", pszerror);
        return 1;  
    }
    mytest = (Func)dlsym(pdlhandle, "add");  
    pszerror = dlerror();  
    if (0 != pszerror)  {  
        printf("%s\n", pszerror);  
        return 1;  
    } 
    printf("%d\n", mytest(5, 5));
    p_Ver = (int *)dlsym(pdlhandle, "g_Ver");
    pszerror = dlerror();
    if (0 != pszerror)  {
        printf("%s\n", pszerror);
        return 1;
    } 
    printf("%d\n", *p_Ver);
    dlclose(pdlhandle);
    return 0;
}

依旧是使用一样的指令就可以生成执行文件main,但是这次不会检查是否存在addg_Ver

动态加载(dynamic loading)的优势是,可以卸载重新加载,特别适用于动态库模块的升级。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值