ROS引用头文件及动态链接库的方法

(1)引用自定义头文件

自定义一个头文件:add_count.h,预定义 INIT_COUNT = 89 ;函数 add_num()

#ifndef _add_count_
#define _add_count_


#define INIT_COUNT 89

int add_num(int a , int b);


#endif

创建package_h_learn包,
修改CMakeLists.txt: 指定头文件位置,在include文件夹,将.h文件放入include文件夹

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
 include
  ${catkin_INCLUDE_DIRS}
)
....
....
....
add_executable(h_learn src/h_learn.cpp)
target_link_libraries(h_learn ${catkin_LIBRARIES})

h_learn.cpp代码:

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

#include "package_h_learn/add_count.h" //引用自定义的头文件

int add_num(int a , int b)	//头文件函数声明的实现
{
	int sum;
	sum = a + b;
	return sum;
}

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);
    
    int count =INIT_COUNT;	//头文件宏定义初始化INIT_COUNT
    int num;
    num = add_num(count,5);

    while(ros::ok())
    {
        std_msgs::String msg;
        std::stringstream ss;

        ss<<"Hello world  "<<num;

        msg.data = ss.str();
        ROS_INFO(msg.data.c_str());
        pub.publish(msg);
        ros::spinOnce();
        loop_rate.sleep();
    }

    return 0;
}

(2)引用同一工作空间的头文件

创建test_package包,在CMakeList.txt修改:

add_executable(h_learn src/h_learn.cpp)
target_link_libraries(h_learn ${catkin_LIBRARIES})

需要引用的头文件在另一个包package_h_learn的include中,所以需要将package_h_learn中的CMakeList.txt做一些修改:将 include文件夹的头文件 发布出去

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
  INCLUDE_DIRS include
#  LIBRARIES package_h_learn
#  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
)

tesk_pkg.cpp代码如下:

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

#include "package_h_learn/add_count.h"  //引用其它包(package_h_learn)的头文件

int add_num(int a , int b)	//头文件函数声明的实现
{
	int sum;
	sum = a + b;
	return sum;
}

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);
    
    int count =INIT_COUNT;	//头文件宏定义初始化INIT_COUNT
    int num;
    num = add_num(count,15);

    while(ros::ok())
    {
        std_msgs::String msg;
        std::stringstream ss;

        ss<<"Hello world  "<<num;

        msg.data = ss.str();
        ROS_INFO(msg.data.c_str());
        pub.publish(msg);
        ros::spinOnce();
        loop_rate.sleep();
    }

    return 0;
}

(3)引用动态链接库

首先自己创建一个简单的动态链接库用于测试:首先创建multiply.cpp和multiply.h
multiply.cpp

#include "multiply.h"

int multiply(int a, int b)
{
	return a*b;
}

multiply.h

#ifndef _MULTIPLY_H_
#define _MULTIPLY_H_

#ifndef __cpluscplus
extern "C"
{
#endif

	int multiply(int a, int b);

#ifndef __cpluscplus
}
#endif

#endif

接下来生成动态链接库*.so文件,注意-share 和 -fPIC 参数很重要
-share:告诉gcc要生成的是动态链接库
-fPIC:告诉gcc生成的代码是非位置依赖的,方便用于动态链接

g++ multiply.cpp -fPIC -shared -o libmultiply.so

在ros工作空间创建一个包test_package,multiply.h放在include/tesk_pkg目录下,libmultiply.so放在lib目录下。

CMakeLists.txt需要做如下修改:

  1. include_directories :需要包含头文件
  2. link_directories :用于添加第三方库路径,catkin_LIB_DIRS表示创建环境变量,${catkin_LIB_DIRS}为取该环境变量的值,lib是相对于当前软件包所在路径的相对路径
  3. target_link_libraries :引用动态链接库,这里去掉lib前缀,去掉.so,直接写multiply
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
 include
  ${catkin_INCLUDE_DIRS}
)
link_directories(
 lib
  ${catkin_LIB_DIRS}
)

...
...
...
add_executable(test_pkg src/test_pkg.cpp)

#add_dependencies(h_learn test1_generate_message_cpp)

target_link_libraries(test_pkg 
	${catkin_LIBRARIES}
	multiply
)

src/test_pkg.cpp代码如下:

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

#include "test_package/multiply.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);

	//.so
	int num = multiply(5,5);
    while(ros::ok())
    {
        std_msgs::String msg;
        std::stringstream ss;

        ss<<"Hello world  "<<num;

        msg.data = ss.str();
        ROS_INFO(msg.data.c_str());
        pub.publish(msg);
        ros::spinOnce();
        loop_rate.sleep();
    }

    return 0;
}

结果:
在这里插入图片描述

### VSCode 中正确配置和引用 C++ 头文件 为了使 Visual Studio Code (VSCode) 正确识别并支持 C++ 头文件的 `#include` 路径,需要完成以下几个方面的配置: #### 1. IntelliSense 支持头文件路径 IntelliSense 是 VSCode 提供的一种智能感知功能,用于提供语法高亮、自动补全等功能。通过修改 `c_cpp_properties.json` 文件中的 `includePath` 字段可以指定额外的头文件路径。 以下是具体的配置方式: ```json { "configurations": [ { "name": "Linux", "includePath": [ "${workspaceFolder}/**", // 工作区内的所有子目录 "/opt/ros/kinetic/include/**", // 自定义头文件路径示例[^2] "/usr/include/**", // 系统默认头文件路径 "/usr/local/include/**" // 用户安装的第三方库头文件路径 ], "defines": [], "compilerPath": "/usr/bin/g++", // 编译器路径 "cStandard": "c11", // C标准版本 "cppStandard": "c++17", // C++标准版本 "intelliSenseMode": "gcc-x64" // IntelliSense模式 } ], "version": 4 } ``` 上述配置中,`includePath` 定义了 IntelliSense 所需的头文件搜索路径。这使得在编写代码时能够正常解析头文件,并消除错误提示线。 --- #### 2. 编译器支持头文件路径 尽管 IntelliSense 可以通过 `includePath` 解析头文件路径,但这并不意味着编译器会自动找到这些路径。因此,在实际编译过程中还需要向编译命令传递 `-I` 参数来指明头文件位置。 可以通过 `.vscode/tasks.json` 或者构建脚本(如 Makefile)来实现这一目标。以下是一个简单的 `tasks.json` 配置示例: ```json { "version": "2.0.0", "tasks": [ { "label": "build", "type": "shell", "command": "g++", "args": [ "-g", // 启用调试信息 "-Wall", // 开启警告选项 "-o", // 输出文件名 "${fileDirname}/${fileBasenameNoExtension}", "${file}", // 当前活动文件 "-I/usr/local/include/", // 指定头文件路径 "-L/usr/local/lib/" // 指定链接库路径 ], "group": { "kind": "build", "isDefault": true }, "problemMatcher": ["$gcc"] } ] } ``` 此配置会在调用 `g++` 进行编译时附加 `-I` 和 `-L` 参数,从而让编译器也能正确找到所需的头文件和动态库[^4]。 --- #### 3. 测试代码验证 假设有一个自定义头文件 `hello.h` 存在于 `/usr/local/include/` 下面,则可以在项目根目录创建如下测试代码 `main.cpp` 来验证配置是否成功: ```cpp #include <iostream> #include "hello.h" void Hello() { std::cout << "Hello from hello.h!" << std::endl; } int main() { Hello(); return 0; } ``` 如果一切配置无误,运行该程序应能打印出预期的结果字符串。 --- #### 4. 调试配置 为了让调试工具也能够加载正确的符号表以及依赖项,还需调整 `.vscode/launch.json` 文件的内容。下面是一份典型的调试配置模板: ```json { "version": "0.2.0", "configurations": [ { "name": "(gdb) Launch", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/a.out", // 替换为目标可执行文件的实际路径 "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": true, "MIMode": "gdb" } ] } ``` 注意其中 `"program"` 字段应当指向最终生成的目标二进制文件的位置[^3]。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值