22

想要将 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 并直接传递绑定函子,但随后我得到类似的错误:

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

5 回答 5

42

有没有人注意到接受的答案只适用于微不足道的情况?function<>::target() 返回可以绑定到 C 回调的对象的唯一方法是,如果它是使用可以绑定到 C 回调的对象构造的。如果是这种情况,那么您可以直接绑定它并跳过所有 function<> 废话开始。

如果你仔细想想,没有任何神奇的解决方案。C 风格的回调存储为指向可执行代码的单个指针。任何重要的 boost::function<> 都需要至少两个指针:一个指向可执行代码,另一个指向设置调用所需的数据(例如,在绑定成员的情况下,“this”指针功能)。

将 boost::function 和 boost::bind 与 C 回调一起使用的正确方法是创建一个满足回调签名的 shim 函数,确定要调用哪个函数<>,然后调用它。通常,C 回调对于“用户数据”会有某种 void*;那是你存放函数指针的地方:

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

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

于 2010-08-10T21:32:04.930 回答
12

我认为您想使用 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;
}
于 2008-11-11T23:01:08.063 回答
4

你能让它与绑定一起工作吗?

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

这是设计使然。基本上,由于bind返回一个完全不同的类型,所以这是不可能的。基本上,活页夹代理对象不能转换为 C 函数指针(因为它不是一个:它是一个函数对象)。返回的类型boost::bind很复杂。当前的 C++ 标准不允许做你想做的事。C++0x 将配备一个decltype表达式,可用于实现如下目的:

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

请注意,这可能有效,也可能无效。我没有办法测试它。

于 2009-02-04T16:56:20.917 回答
2

请参阅 boost 邮件页面 [boost] [Function] 将 target() 与 boost::mem_fn 和 boost::bind 一起使用时出现问题

于 2009-02-27T03:21:11.433 回答
0

你能让它与绑定一起工作吗?

#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;
}

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

于 2009-02-04T16:45:41.453 回答