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

来源:互联网 发布:淘宝嘉年华什么意思 编辑:程序博客网 时间:2024/04/27 19:17

本文介绍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
原创粉丝点击