前面几节的文章里提到过“通过一定的技术手段,通知远程服务器调用某个函数来执行相应的功能”,本片文章分析服务端如何使用std::bind函数,统一函数调用形式。
1、先看一个简单的例子:
温馨提示:std::bind
除了绑定普通函数,还可以绑定类的成员函数,当绑定的是类的非静态成员函数时,此时std::bind
至少需要传递两个参数,第一个参数为类的成员函数,需要通过&类名::成员函数
的方式填入参数;第二个参数为类对象或者类对象指针(若std::bind
发生在某个类的成员函数内,则传递这个类的this指针,见最后buttonrpc源码)。
// 全局函数:只有一个int型参数
void globalFunc(int value)
{std::cout << __FUNCTION__ << " value = " << value << std::endl;
}class A
{
public:// 类中成员函数:两个参数,但最后一个是int型参数void classFunc(double valueA, int valueB){std::cout << __FUNCTION__ << " valueA = " << valueA << " valueB = " << valueB << std::endl;}// 类中静态成员函数:三个参数,但最后一个是int型参数static void classStaticFunc(char valueA, double valueB, int valueC){std::cout << __FUNCTION__ << " valueA = " << valueA << " valueB = " << valueB << " valueC = " << valueC << std::endl;}
};int main()
{std::map<std::string, std::function<void(int)>> mapData;A *a = new A;auto f1 = std::bind(globalFunc, std::placeholders::_1);mapData["global_func"] = f1;auto f2 = std::bind(&A::classFunc, a, 2.3, std::placeholders::_1);mapData["class_func"] = f2;auto f3 = std::bind(&A::classStaticFunc, 'c', 2.3, std::placeholders::_1);mapData["class_static_func"] = f3;mapData["global_func"](1);mapData["class_func"](2);mapData["class_static_func"](3);system("pause");return 0;
}
可以看到,型如上面的3个函数,故意设定了最后一个参数类型为int
。这样,不管是全局函数还是类的成员函数,都可以通过std::bind
的方式,提前绑定已知参数,得到std::function<void(int)>
类型的函数对象,这样便可以统一存储在std::map<std::string, std::function<void(int)>>
类型的容器中。
2、buttonrpc源码中的例子:
template<typename F>
inline void buttonrpc::bind( std::string name, F func )
{m_handlers[name] = std::bind(&buttonrpc::callproxy<F>, this, func, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
}template<typename F, typename S>
inline void buttonrpc::bind(std::string name, F func, S* s)
{m_handlers[name] = std::bind(&buttonrpc::callproxy<F, S>, this, func, s, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
}
上面的buttonrpc::bind( std::string name, F func )
函数内,绑定成员函数buttonrpc::callproxy<F>
,并将成员this
传递进入,完成这2个必要参数后,将已知函数func传入,完成早期绑定;将后面的三个占位符作为晚期绑定。
同理,buttonrpc::bind(std::string name, F func, S* s)
函数内,绑定成员函数buttonrpc::callproxy<F, S>
,并将成员this
传递进入,完成这2个必要参数后,将已知函数func和s传入,完成早期绑定;将后面的三个占位符作为晚期绑定。
int main()
{buttonrpc server;server.as_server(5555);server.bind("foo_1", foo_1);server.bind("foo_2", foo_2);server.bind("foo_3", std::function<int(int)>(foo_3));server.bind("foo_4", foo_4);server.bind("foo_5", foo_5);ClassMem s;server.bind("foo_6", &ClassMem::bar, &s);std::cout << "run rpc server on: " << 5555 << std::endl;server.run();return 0;
}