c++ - 如何将 boost::bind(&myClass::fun, this, _1, _2, _3) 转换为 typedef void (*fun)(arg1, arg2, arg3)?

标签 c++ boost boost-bind c++03

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

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

在文档中有一个 sample of usage (page 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);
}

我将这个示例代码复制到我的类(class)防御中,所以我的类(class)获得了这个功能,我将能够进行这样的转换:

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

而不是像 Bullet 教程中的 dispatcher->setNearCallback(MyNearCallback); 这样的 C。

但是我的 VS2010 sp1 给我一个错误:

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

所以我想知道如何将 boost::bind 转换为这样的 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'

我也试过as described here :

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'指针”并不意味着它产生了一个普通的函数!

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

如果您不能随回调传递任何其他数据,我的意思是,如果回调注册允许您仅提供回调指针,那么它几乎是死路一条。除非你用 ie 做一些或多或少丑陋或有风险的解决方法,否则你无法逃避。全局静态数据或动态代码生成..

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

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

关于c++ - 如何将 boost::bind(&myClass::fun, this, _1, _2, _3) 转换为 typedef void (*fun)(arg1, arg2, arg3)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14803922/

相关文章:

c++ - OpenGL:vertexArray 与 glBegin()

c++ - 从重载集中检索指向最佳匹配的指针而不调用

C++:BOOST-bind 错误:没有匹配的函数可用于调用 'bind(<未解析的重载函数类型>, ...?

c++ - 用零初始化类成员

c++ - 如何检查网站是否包含 Flash

c++ - 在 'abs(double&)' 中重载 "avg += abs(num)"

c++ - 如何取消 boost asio io_service post

c++ - 如何将boost文档添加到qt creator

C++ Boost线程库拉入整个开发环境

c++ - 如何从模板签名创建 boost::function