【ROS】动态链接库(.so文件)的生成和使用
- 引言
- 1.生成so文件
- 2.调用so文件
- 3.运行结果
- 结语
引言
由于项目有涉及到源代码是否交付的选项,想着如果不交付源代码,那就得把程序封装好,但想着还是应该留一点开发空间给别人,所以就想着能不能把方法都变成动态链接库,只对其开放功能使用,不开放源代码编辑。
想着目前网上还没有详细介绍这一部分的内容,在之前自己摸索的经验传授给大家。
包的源代码链接可以点击这里。
1.生成so文件
在同一个文件夹下创建hello类文件,分别是hello.h和hello.cpp
hello.h
#ifndef DYNAMIC_CONNECT_HELLO_H
#define DYNAMIC_CONNECT_HELLO_H
class fun{
public:
int a;
int b;
fun(int aa,int bb);
~fun();
int add_a_b();
};
#endif
hello.cpp
#include "hello.h"
int fun::add_a_b() {
return this->a + this->b;
}
fun::fun(int aa, int bb) {
this->a = aa;
this->b = bb;
}
fun::~fun() {
}
在该文件夹下,终端运行
g++ hello.cpp -fPIC -shared -o libhello.so
即可在该文件下获得libhello.so文件
-fPIC
:作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载其加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的
-shared
:产生一个共享对象,然后可以将其与其他对象链接以形成可执行文件。 并非所有系统都支持此选项。 为了获得可预测的结果,在指定此链接器选项时,还必须指定用于编译的相同选项集(-fpic,-fPIC或模型子选项)
-g
:令gcc生成调试信息,该选项可以利用操作系统的“原生格式(native format)”生成调试信息。GDB可以直接利用这个信息,其他调试器也可以使用这个调试信息
-c
:仅执行编译操作,不进行连接操作
-o
:指定生成的输出文件名称
2.调用so文件
在ros的工作空间,创建一个test的包,hello.h放在include/test目录下,libhello.so放在lib目录下(lib目录需要自行创建)。
test的src下需要创建main.cpp,代码如下
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
#include "dynamic_connect/hello.h"
int main(int argc, char **argv)
{
ros::init(argc,argv,"h_learn");
ros::NodeHandle n;
ros::Publisher pub = n.advertise<std_msgs::String>("listener",1000);
ros::Rate loop_rate(10);
fun *f = new fun(4,2);
int num2 = f->add_a_b();
delete f;
f = NULL;
while(ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss <<"Hello world " << num2;
msg.data = ss.str();
ROS_INFO(msg.data.c_str());
pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
CMakeLists.txt如下
cmake_minimum_required(VERSION 3.0.2)
project(dynamic_connect)
find_package(catkin REQUIRED COMPONENTS
roscpp
rosmsg
rospy
)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES dynamic_connect
# CATKIN_DEPENDS roscpp rosmsg rospy
# DEPENDS system_lib
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
link_directories(
lib
${catkin_LIB_DIRS}
)
add_executable(main src/main.cpp)
target_link_libraries(main
${catkin_LIBRARIES}
hello
)
具体的修改地方如下
- include_directories 需要包含include文件夹;
- link_directories 需要添加lib路径,catkin_LIB_DIRS表示创建环境变量,${catkin_LIB_DIRS}为取该环境变量的值,lib是相对于当前软件包所在路径的相对路径;
- target_link_libraries :引用动态链接库,这里去掉lib前缀,去掉.so后缀,直接写hello
3.运行结果
代码运行结果如下
[ INFO] [1620976666.758420253]: Hello world 6
[ INFO] [1620976666.858414282]: Hello world 6
[ INFO] [1620976666.958412370]: Hello world 6
[ INFO] [1620976667.058414110]: Hello world 6
[ INFO] [1620976667.158418228]: Hello world 6
[ INFO] [1620976667.258414183]: Hello world 6
[ INFO] [1620976667.358422537]: Hello world 6
[ INFO] [1620976667.458416599]: Hello world 6
结语
其实使用动态链接库还是很简单的,只是以前没有接触过,所以还是对这里面的内容比较陌生,但真正做出来之后,其实发现世上的事情都正如卖油翁一样:“无他,但手熟尔。”
与诸君共勉。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)