我有一个C ++库,它应该将一些system \ resource调用作为来自链接应用程序的回调公开。例如:接口应用程序(使用该库)可以发送套接字管理回调函数 - 发送,接收,打开,关闭等,库将使用此实现代替库的实现。 (这种方式使应用程序能够自己管理套接字,可能很有用)。 这个库还需要公开更多的回调,比如密码验证,所以我想知道是否有一种首选方法可以在一个API中公开回调发送选项。 类似的东西:
int AddCallbackFunc (int functionCallbackType, <generic function prototype>, <generic way to pass some additional arguments>)
然后在我的库中,我将根据functionCallbackType参数将回调分配给相应的函数指针。
有没有办法以通用的方式实现它,它适合任何函数原型和任何其他参数?
您的帮助将不仅仅是... 谢谢!
答案 0 :(得分:3)
为什么不接受0参数functor并让用户在注册之前使用boost::bind
来构建参数?基本上是示例(调用而不是商店,但你明白了):
#include <tr1/functional>
#include <iostream>
void callback(const std::tr1::function<int()> &f) {
f();
}
int x() {
std::cout << "x" << std::endl;
return 0;
}
int y(int n) {
std::cout << "y = " << n << std::endl;
return 0;
}
int main(int argc, char *argv[]) {
callback(x);
callback(std::tr1::bind(y, 5));
}
编辑:有一个选项B,它基本上实现了绑定所带来的结构,以存储所有需要的信息和多态性的继承...它变得一团糟。我不推荐它,但它会起作用。您还可以通过强制返回int
类型来避免悲伤,但这只能为您节省一些时间。
#include <iostream>
struct func_base {
virtual int operator()() = 0;
};
// make one of these for each arity function you want to support (boost does this up to 50 for you :-P
struct func0 : public func_base {
typedef int (*fptr_t)();
func0(fptr_t f) : fptr(f) {
}
virtual int operator()() { return fptr(); }
fptr_t fptr;
};
// demonstrates an arity of 1, templated so it can take any type of parameter
template <class T1>
struct func1 : public func_base {
typedef int (*fptr_t)(T1);
func1(fptr_t f, T1 a) : fptr(f), a1(a) {
}
virtual int operator()() { return fptr(a1); }
fptr_t fptr;
T1 a1;
};
void callback(func_base *f) {
(*f)();
}
int x() {
std::cout << "x" << std::endl;
return 0;
}
int y(int n) {
std::cout << "y = " << n << std::endl;
return 0;
}
int main(int argc, char *argv[]) {
// NOTE: memory leak here...
callback(new func0(x));
callback(new func1<int>(y, 5));
}
答案 1 :(得分:1)
如果您不想使用任何可用的C ++选项; std :: tr1 :: function,functors,带有公共基类等的多态性,你可以使用C方法。
客户端将回调和指向其参数的指针作为void *传递,然后回调在调用时将void *转换为正确的类型。你需要在回调旁边存储void *,你需要非常小心对象的生命周期。
int AddCallbackFunc (int type, int(*callback)(void*), void* callbackData)
答案 2 :(得分:1)
可以使用模板和类型擦除的组合来完成。
我们的想法是采用任何类型并将其包装到具有已知接口的对象中。
class CallbackBase
{
public:
virtual ~CallbackBase();
virtual void execute();
};
template <class T>
class Callback: public CallbackBase
{
public:
explicit Callback(T functor): mFunctor(functor) {}
void execute() { mFunctor(); }
private:
T mFunctor;
};
现在,我们可以把它包起来:
template <class Function>
int AddCallbackFunc (int functionCallbackType, Function f)
{
std::auto_ptr<CallbackBase> c(new Callback<Function>(f));
// do something with `c`.
}
我把它留给你来绑定参数,没有库的方法是创建一个仿函数。
答案 3 :(得分:0)
听起来你正在寻找一个Functor。基本上是每种类型回调的类,其中参数为数据成员,operator()
用于调用功能。