C++ ROS与boost:bind()使用详解
作者:Amelie_xiao
1. boost::bind
boost::bind
是标准库函数std::bind1st
和std::bind2nd
的一种泛化形式。其可以支持函数对象、函数、函数指针、成员函数指针,并且绑定任意参数到某个指定值上或者将输入参数传入任意位置。
1.1 通过functions和function pointers使用bind
给定如下函数:
int f(int a, int b) { return a + b; } int g(int a, int b, int c) { return a + b + c; }
- 可以绑定所有参数,如:
bind(f, 1, 2)等价于f(1, 2); bind(g, 1, 2, 3)等价于g(1, 2, 3);
- 也可以选择性地绑定参数,如:
bind(f, _1, 5)(x)等价于f(x, 5),其中_1是一个占位符,表示用第一个参数来替换;
bind(f, _2, _1)(x, y)等价于f(y, x);
bind(g, _1, 9, _1)(x)等价于g(x, 9, x);
bind(g, _3, _3, _3)(x, y, z)等价于g(z, z, z);
说明:
传入bind函数的参数一般为变量的copy,如:
int i = 5; bind(f, i, _1);
比如:
void func(int a, int b, int c); boost::bind(func, 7, _1, _2);
boost::bind()
会返回一个函数对象,所以boost::bind(func, 7, _1, _2)
得到一个函数对象ob
,即ob = boost::bind(func, 7, _1, _2)
。当我们调用ob(3,4)
时,相当于调用func(7,3,4)
,如果连着一起写那就是boost::bind(func, 7, _1, _2)(3, 4)
;
需要注意的一点是,boost::bind()
里的参数个数一定要与被bind包括的函数的形参个数相同,否则这个bind函数对象ob就无法生成并报错。
如果想传入变量的引用,可以使用boost::ref
和boost::cref
,如:
int i = 5; bind(f, ref(i), _1); bind(f, cref(i), _1);
1.2 通过function objects使用bind
struct F { int operator()(int a, int b) { return a – b; } bool operator()(long a, long b) { return a == b; } }; F f; int x = 100; bind<int>(f, _1, _1)(x); // f(x, x)
可能某些编译器不支持上述的bind语法,可以用下列方式代替:
boost::bind(boost::type<int>(), f, _1, _1)(x);
默认情况下,bind拥有的是函数对象的副本,但是也可以使用boost::ref和boost::cref来传入函数对象的引用,尤其是当该function object是non-copyable或者expensive to copy。
1.3 通过pointers to members使用bind
bind将传入的成员(数据成员和成员函数)指针作为第一个参数,其行为如同使用boost::mem_fn将成员指针转换为一个函数对象,即:
bind(&X::f, args);
等价于bind<R>(mem_fn(&X::f), args)
,其中R为X::f的返回类型(成员函数)或类型(数据成员)。
struct X { bool f(int a); }; X x; shared_ptr<X> p(new X); int i = 5; bind(&X::f, ref(x), _1)(i); // x.f(i) bind(&X::f, &x, _1)(i); // (&x)->f(i) bind(&X::f, x, _1)(i); // x.f(i) bind(&X::f, p, _1)(i); // p->f(i)
如:
cb = boost::bind(&NodeExample::configCallback, node_example, _1, _2);
其中的 node_example
是指针变量NodeExample *node_example = new NodeExample();
因此boost::bind(&NodeExample::configCallback, node_example, _1, _2)
的意思就是 node_example -> configCallback(x, y);
又如:
boost::bind(&MyNode::doneCb, this, _1, _2);
意思就是this -> doneCb(x, y)
这里的x,y 分别为第一个和第二个输入参数。
2. ROS与bind()
2.1
当我们订阅一个消息时候,会调用一个返回函数。如:
ros::Subscriber topic_sub=n.subscribe<std_msgs::Int8>("/topic", 10, Callback);
这样Callback函数应该包含一个参数,即:
void Callback(const std_msgs::Int8::ConstPtr& msg){}
但是,如果我们想要多参数传入的话,就需要使用boost库中的bind函数。例如,当我们的回调函数是这样的:
void Callback(const std_msgs::Int8::ConstPtr& msg, int& x, int& y){}
2.2 示例
#include <ros/ros.h> #include <std_msgs/Int8.h> int index1 = 1; int index2 = 2; void Callback(const std_msgs::Int8::ConstPtr &msg, int &x, int &y) { printf("%d", *msg); printf("%d \r\n", x); printf("%d \r\n", y); } void Callback(const std_msgs::Int8::ConstPtr &msg) { printf("%d \r\n", *msg); } int main(int argc, char **argv) { ros::init(argc, argv, "multi_callback"); ros::NodeHandle n; ros::NodeHandle private_nh("~"); int rate; private_nh.param("rate", rate, 40); // ros::Subscriber scan_sub=n.subscribe<std_msgs::Int8>("/topic", 10, //boost::bind(&Callback, _1, index1, index2));//① ros::Subscriber scan_sub = n.subscribe<std_msgs::Int8>("topic", 10, Callback);//② ros::Rate r(rate); while (n.ok()) { ros::spinOnce(); r.sleep(); } return 0; }
当使用①函数时:
ros::Subscriber scan_sub=n.subscribe<std_msgs::Int8>("/topic", 10, \ boost::bind(&Callback, _1, index1, index2));//①
返回函数调用的是:
void Callback(const std_msgs::Int8::ConstPtr &msg, int &x, int &y) { printf("%d", *msg); printf("%d \r\n", x); printf("%d \r\n", y); }
当使用②函数时:
ros::Subscriber scan_sub = n.subscribe<std_msgs::Int8>("topic", 10, Callback);//②
返回函数调用的是:
void Callback(const std_msgs::Int8::ConstPtr &msg) { printf("%d \r\n", *msg); }
参考资料
到此这篇关于C++ ROS与boost:bind()详解的文章就介绍到这了,更多相关C++ ROS与boost:bind()内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!