1 boost:bind()
bind接收的第一个参数必须是一个可调用的对象f,包括函数、函数指针、函数对象和成员函数指针,之后bind最多接受9个参数,参数数量必须与f的参数数量相等,这些参数被传递给f作为形参。
绑定完成后,bind会返回一个函数对象ob(类似auto ob = boost::bind(f,...)
),它内部保存了f的拷贝,具有operator(),返回值类型被自动推导为f的返回类型。在发生调用时这个函数对象ob将把之前存储的参数转发给f完成调用.
如:
void func(x,y);
那么,他等价于一个具有无参operator()的bind函数对象调用:
auto ob = boost::bind(func,a1,a2)();//ob()==func(a1,a2);
//因为bind()里没有占位符,所以ob()无参数,a1,a2作为参数直接输入func
一般来说boost::bind有两种方式的调用,一种是对自由方法,也即非类方法, 一种是对类方法.
- 对自由方法来说,直接boost::bind(函数名, 参数1,参数2,…)
- 对类方法来说,直接boost::bind(&类名::方法名,类实例指针,参数1,参数2)
1.1 非类方法
bind(f, _1, 5)(x)等同于f(x, 5).这里的 _1 相当于一个占位符,用来代替第一个输入参数。又如:
bind(f, 5, _1)(x); // f(5, x)
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(g, _1, _1, _1)(x, y, z); // g(x, x, x)
比如:
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就无法生成并报错.
1.2 类方法
如:
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); }