Linux 平台 C /C++ 动态库的制作与使用方式

《Linux 平台如何制作自己的 C /C++ 静态库》 中简单介绍了静态库的制作方法,但实际上动态库的使用更为广泛,至于原因,在 《Linux 平台基于 C /C++ 的静态库和动态库的区别》 一文中已有说明。本文介绍动态库的制作方法以及两种使用方式。

1. 示例程序

test.c 代码如下:

#include"test.h"
void test()
{
    printf("I am test;hello,编程珠玑
");
}

test.h 代码如下:

#include
void test();

代码比较简单,只有一个 test 函数,用于打印一段字符串。

2. 制作动态库

只需要执行以下命令即可:

$ gcc test.c -fPIC -shared -o libtest.so

其中的 -fPIC 表示生成位置无关代码,以便在只有一个副本的情况下供多个应用程序共享。

通过 readelf 命令查看 elf 文件类型:

$ readelf -h libtest.so
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64

从结果中可以看到,libtest.so 为 Shared object file。

3. 使用动态库

常见有两种使用方式,一种是加载时链接,另一种是使用时链接。

3.1 加载时链接

加载时链接在代码中不需要做额外的动作,像使用静态库一样使用即可。例如 main.c 如下:

#include
#include"test.h"
int main(void)
{
    test();
    return 0;
}

编译链接:

$ gcc -o main main.c -L . -ltest

其中 - L 指定从当前目录下寻找动态库 libtest.so,否则会找不到。

然后我们还可以通过 ldd 命令查看其依赖的动态库:

$ ldd main
    Linux-vdso.so.1 =>  (0x00007ffd57757000)
    libtest.so => not found
    libc.so.6 => /lib/x86_64-Linux-gnu/libc.so.6 (0x00007f84c13f6000)
    /lib64/ld-Linux-x86-64.so.2 (0x00007f84c17c0000)

其中就有我们自己制作的 libtest.so。

运行:

$ ./main
./main: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

很不幸,程序并没有如预期的那样运行起来,而是报错了。这是为什么呢?

其实我们在使用 ldd 命令查看的时候,就注意到:

libtest.so => not found

它并不能找到这个动态库,因为它会默认从系统库的路径去查找这个库,但是我们并没有把这个库放到系统路径下,因此会找不到了。

我们有两种方法解决这个问题:

  • 将 libtest.so 库放到系统路径下
  • 指定当前进程动态库搜索路径

第一种方法:

$ cp libtest.so /usr/lib
$ ./main
I am test;hello,编程珠玑

第二种方法:

$ export LD_LIBRARY_PATH=./
$ ./main
I am test;hello,编程珠玑

导入 LD_LIBRARY_PATH 环境变量,指定库搜索路径,使得 main 程序能够找到 libtest.so。

此时再看:

$ ldd main
    Linux-vdso.so.1 =>  (0x00007ffcdebdf000)
    libtest.so => ./libtest.so (0x00007f494a45f000)
    libc.so.6 => /lib/x86_64-Linux-gnu/libc.so.6 (0x00007f494a095000)
    /lib64/ld-Linux-x86-64.so.2 (0x00007f494a661000)

libtest.so 不再是 not found 了。

3.2 使用时链接

为了使用这种方式,需要使用几个函数 dlopen,dlsym,dlclose,dlerror,其原型分别如下:

  • 分享于 · 2019.07.29 13:43 · 阅读 · 2254

[版权声明] :本文系网友分享,仅以非商业性的交流和科研为目的,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与本网( friends@stuch.cn )联系!我们将协调给予处理。转载授权码:确权中,请原作者尽快与我们取得联系,阅读原文(请登录)..

0 条评论

请先 登录 后评论
猜猜我是谁
甜也 -研究生

8
提问
13
回答
6
文章