我有一个库,我可能不会改变。它有一个包含函数指针的结构,它是某些事件的回调函数。考虑:
// library code (.h file)
typedef int (callback_function)(int arg1, double arg2);
struct callbacks_struct
{
...
callback_function *callback;
...
};
我正在为这个低级别的东西编写一个C ++包装器。考虑我有一个班级:
class Wrapper
{
public:
int Callback(int arg1, double arg2);
};
现在我想绑定Wrapper::Callback
以在创建结构callback_struct
时用作回调:
struct callback_struct x[] =
{
{
...
// put a Wrapper::Callback as a callback
...
},
{0, 0, 0, 0}
}
显然,没有一些中间功能就无法做到这一点。一种方法是创建Wrapper
类的全局对象并使用它:
std::shared_ptr<Wrapper> gWrapper;
void foo()
{
struct callback_struct x[] =
{
{
...
my_plain_callback,
...
},
{0, 0, 0, 0}
}
}
int my_plain_callback(int arg1, double arg2)
{
return gWrapper->Callback(arg1, arg2);
}
但我需要一个线程安全的解决方案,因此在这种情况下使用全局变量似乎是问题的根源。
有谁知道更好的解决方案?
感谢。
答案 0 :(得分:2)
使用线程局部变量作为回调状态。
或者去硬核路由并使用一些与平台相关的代码来生成一个注入指针的存根。
答案 1 :(得分:1)
它可以帮到你:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <stdexcept>
#include <mutex>
class Wrapper
{
typedef std::mutex mutex_type;
typedef std::unique_lock<mutex_type> locker;
public:
typedef boost::function<int(int,double)> call_backtype;
static int callBackFunction(int arg1_, double arg2_)
{
locker l(_mutex);
if ( my_call.empty() ) {
throw std::runtime_error("No callback function was set!");
}
return my_call(arg1_,arg2_);
}
static void setCallBack( const call_backtype& func_ )
{
locker l(_mutex);
_my_call = func_;
}
private:
static mutex_type _mutex;
static call_backtype _my_call;
Wrapper(void){}
};
class any_other_class
{
int do_anything(int arg1_, double arg2_);
void setThisAsCallback()
{
Wrapper::setCallBack(boost::bind(&any_other_class::do_anything,this,_1,_2));
}
};
// to C interface (use the static method):
setCallBack(&Wrapper::callBackFunction);