如何投射到它 boost::bind(&myClass::fun, this, _1, _2, _3) 到 typedef void (*fun)(arg1, arg2, arg3)?

How to cast to it boost::bind(&myClass::fun, this, _1, _2, _3) to typedef void (*fun)(arg1, arg2, arg3)?

本文关键字:fun arg3 typedef void arg1 arg2 this boost 何投射 bind myClass      更新时间:2023-10-16

在lib Bullet中定义了一种类型:

typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);

在这些文档中,有一个用法示例(第23页):

void MyNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) {
        // Do your collision logic here
        // Only dispatch the Bullet collision information if you want the physics to continue
        dispatcher.defaultNearCallback(collisionPair, dispatcher, dispatchInfo);
}

我把这个示例代码复制到了我的类防御中,所以我的类得到了这个函数,我将能够进行这样的强制转换,比如:

    dispatcher->setNearCallback(boost::bind(&BulletAPIWrapper::MyNearCallback, this, _1, _2, _3));

而不是像Bullet教程中的CCD_ 1那样的C。

然而,我的VS2010 sp1给了我一个错误:

Error   44  error C2664: 'btCollisionDispatcher::setNearCallback' : cannot convert parameter 1 from 'boost::_bi::bind_t<R,F,L>' to 'btNearCallback'

所以我想知道如何将boost::绑定到这样的typedef?

是否可能具有静态类函数(或至少类似全局函数):

void MyNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo, BulletAPI* api) {
}

调用dispatcher->setNearCallback( boost::bind(MyNearCallback, _1, _2, _3, this));

因为它给我带来了几乎相同的错误:

Error   44  error C2664: 'btCollisionDispatcher::setNearCallback' : cannot convert parameter 1 from 'boost::_bi::bind_t<R,F,L>' to 'btNearCallback'

我也尝试过这里描述的:

template<unsigned ID,typename Functor>
boost::optional<Functor> &get_local()
{
    static boost::optional<Functor> local;
    return local;
}
template<unsigned ID,typename Functor>
typename Functor::result_type wrapper(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
{
    return get_local<ID,Functor>().get()(collisionPair, dispatcher, dispatchInfo);
}
template<typename ReturnType>
struct Func
{
    typedef ReturnType (*type)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
};
template<unsigned ID,typename Functor>
typename Func<typename Functor::result_type>::type get_wrapper(Functor f)
{
    (get_local<ID,Functor>()) = f;
    return wrapper<ID,Functor>;
}
struct NearCallbackWrapper
{
    class BulletAPI;
    void MyNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) {
        std::cout << "called" << std::endl;
    }
};
//....
dispatcher->setNearCallback( get_wrapper<0>(  boost::bind(&NearCallbackWrapper::MyNearCallback,this) ) );

但我从中得到了这样的错误:

error C2664: 'btCollisionDispatcher::setNearCallback' : cannot convert parameter 1 from 'void (__cdecl *)(btBroadphasePair &,btCollisionDispatcher &,const btDispatcherInfo &)' to 'btNearCallback'

为什么你认为你"应该能够像..一样投射?"?setNearCallback当然希望传递一个正常的函数指针,而BIND则产生完全不同的结果。。

Bind生成一个不需要"this"指针的"可调用的东西",这并不意味着它生成了一个普通函数!

要正确处理绑定的成员函数,您仍然需要至少两个指针的空间,而正常的函数指针是一个指针。所有允许您注册回调的sane*)API也允许您在回调的同时传递一些"用户数据"-在这种情况下,您可以使用它来创建小包装,将调用重定向到绑定的成员函数。这已经在很多地方讨论过了。。例如,请参见:https://stackoverflow.com/a/3453616/717732

如果你不能在回调的同时传递任何额外的数据,我的意思是,如果回调注册只允许你提供回调指针,那么它几乎是死胡同。除非你对全局静态数据或动态代码生成做一些或多或少丑陋或有风险的解决方案,否则你无法逃脱这种情况。。

*)这纯粹是个人观点。我所说的"理智"是指"对对象友好"。低级别API通常并不是严格意义上的,而是尽可能节约资源——因此它迫使你自己做脏活,因为他们想真正节省那4/8字节。有时,有时,这实际上会产生巨大的影响-他们可能会更容易地传递4/8b回调,因为它适合一个寄存器,所以很容易复制(而指针+用户数据需要2个以上的寄存器),对它的操作"更原子"等等。然而,大多数情况下,这样做是为了痛苦地强调只有一个回调可以注册。在这种情况下,无论它是某个对象的绑定成员函数,还是只是一个全局静态函数,它实际上都没有什么区别:总之,只能有一个,所以不管怎样,只要让它工作就行了。如果是这种情况,那么只需为对象指针和小包装器使用全局静态变量。嗯,除了美学…:

static MyObject* target;
void wrapper(..params..)
{
    target->method_to_be_called(..params..);
}
// then, register it:
target = &object_to_be_called;  //  there can be only one object
setCallback(&wrapper);          // / and only one callback registered