将 boost::function 降级为普通函数指针
想要将 boost::bind 传递给需要普通函数指针(相同签名)的方法.
want to pass boost::bind to a method expecting a plain function pointer (same signature).
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 并直接传递绑定的函子,但是我得到了类似的错误:
I can avoid storing a boost::function and just pass the bound functor directly, but then I get similar error:
error C2664: 'blah(void (__cdecl *)(type *,void *))' : cannot convert parameter
1 from 'boost::_bi::bind_t<R,F,L>' to 'void (__cdecl *)(type *,void *)'
推荐答案
有没有人注意到接受的答案只有效与琐碎的案件?function<>::target() 将返回可以绑定到 C 回调的对象的唯一方法是,如果它是用可以绑定到 C 回调的对象构造的.如果是这种情况,那么您可以直接绑定它并跳过所有函数<>开始时的废话.
Has anyone noticed that the accepted answer only works with trivial cases? The only way that function<>::target() will return an object that can be bound to a C callback, is if it was constructed with an object that can be bound to a C callback. If that's the case, then you could have bound it directly and skipped all of the function<> nonsense to begin with.
如果你仔细想想,这个问题没有任何神奇的解决方案.C 样式的回调存储为指向可执行代码的单个指针.任何重要的 boost::function<> 都至少需要两个指针:一个指向可执行代码,另一个指向设置调用所需的数据(例如,'this' 指针,在绑定成员的情况下)功能).
If you think about it, there isn't any magic solution to this. A C-style callback is stored as a single pointer which points to executable code. Any nontrivial boost::function<> is going to need at least two pointers: one to the executable code, the other to the data that's needed to set up the call (e.g. the 'this' pointer, in the case of a bound member function).
在 C 回调中使用 boost::function 和 boost::bind 的正确方法是创建一个满足回调签名的 shim 函数,找出要调用的函数<>,然后调用它.通常,C 回调会为用户数据"提供某种 void*;这就是你隐藏函数指针的地方:
The right way to use boost::function and boost::bind with C callbacks is to create a shim function that satisfies the callback signature, figures out which function<> to call, and calls it. Usually C callbacks will have some kind of a void* for 'user data'; that's where you stash your function pointer:
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);
当然,如果您的回调签名不包含某种用户数据指针,那您就不走运了.但是任何不包含用户数据指针的回调在大多数实际场景中已经无法使用,需要重写.
Of course, if your callback signature doesn't include some kind of user data pointer, you're out of luck. But any callback that doesn't include a user data pointer is already unusable in most real-world scenarios, and needs to be rewritten.
相关文章