生成与调用C++动态链接库(so文件)


前言

动态链接库是代码重用和模块化的重要工具,它使得将功能封装为独立的库更加容易,同时还可以动态加载和升级这些库,提高了程序的灵活性和可维护性。
当我们希望将C++源码编译成动态链接库,并在其他应用程序中调用这个动态链接库,是这篇文章的应用场景。这篇文档将介绍如何创建、编译、链接和调用C++动态链接库。
PS:本文以下内容根据我实际工作项目编写,不采用demo的形式。


生成C++动态链接库

步骤1:编写C++源码

首先,编写C++源码文件,包括所需的类和函数。(看这篇文章的应该都有源码了吧!)
我实际的项目文件如下:
在这里插入图片描述
现在需要把ai_main.cpp编译成动态链接库。难点在于(完成后看来也不是什么难点):ai_main.cpp不仅调用了同级目录下的其他文件,还调用了其他路径的下源码文件(opencv等)

步骤2:生成共享库

使用C++编译器将源码编译成共享库,我这里采用的是aarch64-mix210-linux-g++编译工具链:

  1. 在同级目录下创建一个名为"build"的文件夹,该文件夹将用于构建目标文件和.so文件。打开命令行终端并进入到该目录下。
mkdir build && cd build
  1. 运行以下命令,将所有依赖的cpp文件编译为目标文件(.o文件):
aarch64-mix210-linux-g++ -c -fPIC -I/home/data/ai/opencv/include -I/home/data/ai/Ascend/ascend-toolkit/5.10.t20.0.b200/arm64-lmixlinux200/aarch64-linux/include ../*.cpp

-c选项告诉编译器只进行编译而不进行链接操作。
-fPIC选项表示生成位置无关代码,这是生成共享库所必需的。
-I选项指定头文件目录,如果有其他cpp文件中使用了头文件,则需要将其添加到该选项中。
修改于2023年9月20日:添加了优化参数,使得后续生成的so库调用时间降低

aarch64-mix210-linux-g++ -c -fPIC -I/home/data/ai/opencv/include -I/home/data/ai/Ascend/ascend-toolkit/5.10.t20.0.b200/arm64-lmixlinux200/aarch64-linux/include ../*.cpp -O3 -flto -funroll-loops  -finline-functions
  1. 运行以下命令将目标文件链接为共享库文件.so
aarch64-mix210-linux-g++ -shared -o libmy_main.so *.o

-shared选项表示生成共享库文件。
-o选项指定输出文件名。
修改于2023年9月20日:添加了优化参数,使得后续生成的so库调用时间降低

aarch64-mix210-linux-g++ -shared -o libmy_main.so *.o  -O3 -flto -funroll-loops  -finline-functions 

完成后,你将在"build"文件夹中找到生成的libmy_main.so文件,这是可以给别人用来动态链接的共享库。
在这里插入图片描述

在上述命令中可以换成自己的编译工具(例如g++),需要根据实际情况修改文件名和路径。另外,如果代码中有其他库的依赖,你需要确保这些库已经安装并在编译/链接时正确配置了相关选项。

步骤3:验证生成的SO文件

通过运行以下命令来验证生成的SO文件是否可用:

file libmy_main.so

这应该显示类似于以下内容:

libmy_main.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (GNU/Linux), dynamically linked, not stripped

so文件生成成功。

检查符号链接:
运行以下命令,并确保输出中包含后续所需调用函数的定义。

nm libmy_main.so | grep ai_track

输出类似于:

0000000000061218 T ai_track

出现以上结果,说明ai_track函数在生成的共享库libmy_main.so中是可见的。这意味着该函数的定义在共享库中是存在的。ai_track需要替换成自己对外的接口函数,也就是其他程序调用so的函数。

调用C++动态链接库

现在,我们将展示如何在另一个C++程序中调用生成的C++动态链接库。我这是是做的测试,把原来源码编译部分替换成调用生成的so

步骤1:修改原来makefile

# 注释掉原来调用原代码部分
# SMP_SRCSCPP += $(wildcard $(PWD)/../media/ai/src/*.cpp)
# 添加共享库的头文件和库路径
COMM_INC += -I/home/ai/src/build/include
CFLAGS += -L/home/src/build/lib

# 添加共享库的链接标志,例如 libmy_main.so
CFLAGS += -lmy_main

# 如果共享库是C++库,添加C++编译器标志
CFLAGS += -lstdc++

其中:
COMM_INC += -I/home/ai/src/build/include:目录下为so提供的函数接口的头文件,可以直接复用源码中对应的ai_main.h
CFLAGS += -L/home/src/build/lib:确保 -L 选项中指定的共享库路径是正确的,并且包含了包含所需共享库libmy_main.so的目录;
CFLAGS += -lmy_main:通常,共享库名称应该是去掉 lib 前缀和 .so 后缀的部分。在这种情况下,libmy_main.so应该是 -lmy_main

步骤2:编译调用程序

我这里直接在原来的基础上重新编译:

make clean && make -j4

运行完成后会生成可执行文件,我这里可执行文件暂为run_main

步骤3:运行调用程序

运行run_main文件时,需要指定so动态链接库的路径

export LD_LIBRARY_PATH=/path/to/your/library:$LD_LIBRARY_PATH

或者,可以在使用运行时链接:

run_main -rpath /path/to/your/library

这将在运行时为应用程序指定共享库的搜索路径。

无论您选择哪种方法,都确保共享库的路径设置正确,以便您的应用程序可以正确找到和加载所需的共享库。


总结

本文介绍了如何制作C++动态链接库(so文件)以及如何从另一个C++程序中加载和调用该库。本文主要从笔者自身项目出发,其中的过程不一定适用所有人。
如果阅读本文对你有用,欢迎一键三连呀!!!
2023年9月5日14:25:02
在这里插入图片描述

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: C语言中创建动态链接库供C程序使用的步骤如下: 1. 写好要封装的C语言函数或者模块的代码,并将其保存为一个或多个C文件。 2. 编写一个头文件,将要使用的函数或者模块的声明放在该头文件中。 3. 打开终端或者命令提示符,使用GCC编译器将C文件编译为目标文件。命令如下: `gcc -c 文件名.c -o 输出的目标文件名.o` 这样会将C文件编译为目标文件,目标文件是二进制文件,用来存储编译后的机器码。 4. 将编译好的目标文件打包成动态链接库动态链接库的命名规则为"libxxx.so",其中xxx为动态链接库的名字。命令如下: `gcc -shared 目标文件1.o 目标文件2.o -o libxxx.so` 这样会将目标文件打包成动态链接库动态链接库是一个二进制文件,包含了函数或者模块的机器码。 5. 将生成动态链接库文件放置到C程序的运行路径下,使用时可通过指定库的名字链接到该库。 6. 在C程序中引入头文件,并调用动态链接库中的函数或者模块。 以上是使用GCC编译器创建动态链接库供C程序使用的基本步骤。通过这种方式封装功能,可以实现代码的模块化和重用,提高程序的可维护性和可扩展性。 ### 回答2: 使用者使用动态链接库的主要目的是为了方便地重复使用某些功能代码。在C语言中,可以使用如下步骤来创建并使用动态链接库。 首先,创建动态链接库的源代码文件,该文件包含了要提供的功能代码。可以使用C语言编写这个文件,其中可能包含一些函数和全局变量等。 接下来,使用编译器将源代码文件编译成目标文件。在这个过程中,需要使用适当的编译选项来指定生成动态链接库而不是可执行文件。比如,在GCC编译器中,可以使用"-shared"选项来生成动态链接库。 然后,使用编译器将目标文件链接成动态链接库文件。这一步会生成扩展名为".so"(在Linux系统上)或".dll"(在Windows系统上)的文件。在该步骤中,需要提供一些额外的链接选项,以确保正确地生成动态链接库。 最后,使用者可以在自己的C语言程序中引用和使用动态链接库。可以通过在程序中包含相应的头文件并使用相关的函数和变量来调用动态链接库中的功能。 需要注意的是,使用者在编译和链接自己的程序时,需要指定动态链接库的位置和名称,以便在运行时正确加载和使用动态链接库。这可以通过编译选项和链接选项来实现。 总之,通过以上步骤,可以创建一个供C语言程序使用的动态链接库,并在程序中使用其中的功能代码。这样可以提高代码的复用性和可维护性,同时也便于程序的调试和更新。 ### 回答3: 编程语言C中的动态链接库(Dynamic Link Library,简称DLL)是一个可重用的代码和数据集合,可以在不同的程序中被调用。以下是创建动态链接库供C使用的基本步骤: 1. 编写C代码:首先,编写包含所需功能的C代码。将这些代码组织成一个或多个函数,这些函数可以是库的接口。 2. 创建头文件:创建一个头文件(.h文件),其中包含库的函数声明和必要的常量和类型定义。这个头文件将作为客户端程序与动态链接库之间的接口。 3. 编译动态链接库:使用C编译器(例如gcc)将C代码编译成目标文件,使用以下命令生成位置无关的目标文件: ``` gcc -c -fPIC library.c -o library.o ``` 其中,`-c`选项表示只编译不链接,`-fPIC`选项表示生成位置无关的代码,`library.c`是你的源代码文件名,`library.o`是生成的目标文件名。 4. 创建动态链接库:使用以下命令将目标文件创建为动态链接库: ``` gcc -shared -o liblibrary.so library.o ``` 其中,`-shared`选项表示生成动态链接库,`-o liblibrary.so`指定输出的库文件名为`liblibrary.so`。 5. 安装动态链接库:将生成动态链接库文件(`liblibrary.so`)复制到系统的默认库目录(例如`/usr/lib`)。使用以下命令: ``` sudo cp liblibrary.so /usr/lib ``` 注意:根据操作系统和环境设置,可能需要提供管理员权限。 6. 使用动态链接库:在你的C程序中,通过包含头文件(步骤2)并使用函数声明来调用动态链接库中的函数。编译时需要链接动态链接库,可以使用以下命令: ``` gcc client.c -o client -llibrary ``` 其中,`client.c`是你的客户端程序源代码文件名,`-llibrary`表示链接名为`liblibrary.so`的动态链接库。 这样,你就成功地创建了一个动态链接库,供其他C程序调用。在客户端程序中,只需要包含头文件并链接动态链接库,就能使用其中定义的函数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI小笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值