1

我有一个图书馆,我可能不会改变它的来源。它有一个包含函数指针的结构,该指针是某个事件的回调。考虑:

// 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);
}

但我需要一个线程安全的解决方案,所以在这种情况下使用全局变量似乎是问题的根源。

有谁知道更好的解决方案?

谢谢。

4

2 回答 2

2

为回调状态使用线程局部变量。

或者走核心路线并使用一些平台相关的代码来生成一个注入指针的存根。

于 2013-06-13T16:25:39.983 回答
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);
于 2013-06-13T21:38:54.453 回答