将boost :: function降级为普通函数指针

时间:2008-11-11 22:33:30

标签: c++ boost functor

想要将boost :: bind传递给期望普通函数指针(相同签名)的方法。

typedef void TriggerProc_type(Variable*,void*);
void InitVariable(TriggerProc_type *proc);
boost::function<void (Variable*, void*)> triggerProc ...
InitVariable(triggerProc);

error C2664: 'InitVariable' : cannot convert parameter 1 from 
'boost::function<Signature>' to 'void (__cdecl *)(type *,void *)'

我可以避免存储boost :: function并直接传递绑定的functor,但后来我得到了类似的错误:

error C2664: 'blah(void (__cdecl *)(type *,void *))' : cannot convert parameter
1 from 'boost::_bi::bind_t<R,F,L>' to 'void (__cdecl *)(type *,void *)'

5 个答案:

答案 0 :(得分:41)

是否有人注意到accepted answer仅适用于琐碎的案件?函数&lt;&gt; :: target()将返回一个可绑定到C回调的对象的唯一方法是,它是否使用可绑定到C回调的对象构造。如果是这种情况,那么您可以直接绑定它并跳过所有函数&lt;&gt;废话开始。

如果你仔细想想,没有任何神奇的解决方案。 C样式的回调存储为指向可执行代码的单个指针。任何重要的boost :: function&lt;&gt;将需要至少两个指针:一个指向可执行代码,另一个指向设置调用所需的数据(例如,在绑定成员函数的情况下为'this'指针)。

使用boost :: function和boost :: bind与C回调的正确方法是创建一个满足回调签名的填充函数,找出哪个函数&lt;&gt;打电话给它。通常C回调对于'用户数据'会有某种无效*;这就是你存储你的函数指针的地方:

typedef void (*CallbackType)(int x, void* user_data);
void RegisterCallback(CallbackType cb, void* user_data);

void MyCallback(int x, void* userData) {
  boost::function<void(int)> pfn = static_cast<boost::function<void(int)> >(userData);
  pfn(x);
}

boost::function<void(int)> fn = boost::bind(myFunction(5));
RegisterCallback(MyCallback, &fn);

当然,如果你的回调签名不包含某种用户数据指针,那你就不走运了。但是,任何不包含用户数据指针的回调在大多数现实场景中都已无法使用,需要重写。

答案 1 :(得分:11)

我认为你想使用boost :: function的target()成员函数(不是那么满口......)

#include <boost/function.hpp>
#include <iostream>

int f(int x)
{
  return x + x;
}

typedef int (*pointer_to_func)(int);

int
main()
{
  boost::function<int(int x)> g(f);

  if(*g.target<pointer_to_func>() == f) {
    std::cout << "g contains f" << std::endl;
  } else {
    std::cout << "g does not contain f" << std::endl;
  }

  return 0;
}

答案 2 :(得分:3)

  

你可以使用bind吗?

cb_t cb = *g.target<cb_t>(); //target returns null

这是by design。基本上,由于bind返回一个完全不同的类型,因此无法使用它。基本上,绑定器代理对象不能转换为C函数指针(因为它不是一个:它是一个函数对象)。 boost::bind返回的类型很复杂。当前的C ++标准没有任何好的方法来做你想做的事情。 C ++ 0x将使用decltype表达式,可以在此处使用它来实现类似的结果:

typedef decltype(bind(f, 3)) bind_t;
bind_t target = *g.target<bind_t>();

请注意,这可能会也可能不会奏效。我无法测试它。

答案 3 :(得分:2)

答案 4 :(得分:0)

你可以使用bind吗?

#include <boost/function.hpp>
#include <boost/bind.hpp>

void f(int x)
{
    (void) x;
    _asm int 3;
}

typedef void (*cb_t)(int);

int main()
{
    boost::function<void (int x)> g = boost::bind(f, 3);
    cb_t cb = *g.target<cb_t>(); //target returns null
    cb(1);

    return 0;
}

更新:好的,目的是将方法绑定到函数回调中。那么现在呢?