使用boost :: bind替换使用成员函数的自由函数本机回调

时间:2012-01-31 15:35:09

标签: c++ windows boost callback c++-cli

我有C ++ / CLI类包装的本机C ++类,因此C#类可以使用它们。讨厌,但有效。到目前为止,为了将本机回调映射到.NET事件,我在我的包装类中做了类似的事情:

void Wrapper::ManagedEvent::add( Action^ managedEventHandler ){
    m_dManagedEvent += managedEventHandler;
    m_pNativeInstance->registerEventCallback( static_cast<INativeInterface::NativeCallback*>(
        Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate( managedEventHandler ).ToPointer() ) );
}

void Wrapper::ManagedEvent::remove( Action^ managedEventHandler ){
    m_dManagedEvent -= managedEventHandler;
    m_pNativeInstance->registerEventCallback( NULL );
}
  • m_dManagedEventSystem::Action^
  • 本机回调被定义为自由函数;在这种情况下,typedef void __stdcall NativeCallback();,在INativeInterface内。

这很好用,但现在我爱上了Boost,这意味着使用boost::functionboost::bind。这在本地课程之间很有效,但是我想说我想改变我的课程 registerEventCallback功能,以便它收到boost::function<void()>。我如何更改addremove方法?

我想到了这一点,但它迫使我为每个事件编写另一个成员函数,我不确定它是否会构建,因为this是一个跟踪句柄:

void Wrapper::FireManagedEvent(){
    m_dManagedEvent();
}

void Wrapper::ManagedEvent::add( Action^ managedEventHandler ){
        m_dManagedEvent += managedEventHandler;
        m_pNativeInstance->registerEventCallback( boost::bind( &Wrapper::FireManagedEvent, this ) );
    }

有更好的解决方案吗?

更新:根据@Ben Voigt的回答,我尝试了以下内容:

   void Wrapper::ManagedEvent::add( Action^ managedEventHandler ){
        m_dManagedEvent += managedEventHandler;
        m_pNativeInstance->registerEventCallback( static_cast< boost::function< void() > >(
            Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate( managedEventHandler ).ToPointer() ) );
    }

但它给出了编译错误:

2>D:\SVN.DRA.WorkingCopy\DRALibraries\Boost_1_48_0\boost/function/function_template.hpp(112): error C2064: term does not evaluate to a function taking 0 arguments
2>          D:\SVN.DRA.WorkingCopy\DRALibraries\Boost_1_48_0\boost/function/function_template.hpp(110) : while compiling class template member function 'void boost::detail::function::void_function_invoker0<FunctionPtr,R>::invoke(boost::detail::function::function_buffer &)'
2>          with
2>          [
2>              FunctionPtr=void *,
2>              R=void
2>          ]
2>          D:\SVN.DRA.WorkingCopy\DRALibraries\Boost_1_48_0\boost/function/function_template.hpp(907) : see reference to class template instantiation 'boost::detail::function::void_function_invoker0<FunctionPtr,R>' being compiled
2>          with
2>          [
2>              FunctionPtr=void *,
2>              R=void
2>          ]
2>          D:\SVN.DRA.WorkingCopy\DRALibraries\Boost_1_48_0\boost/function/function_template.hpp(722) : see reference to function template instantiation 'void boost::function0<R>::assign_to<Functor>(Functor)' being compiled
2>          with
2>          [
2>              R=void,
2>              Functor=void *
2>          ]
2>          D:\SVN.DRA.WorkingCopy\DRALibraries\Boost_1_48_0\boost/function/function_template.hpp(1043) : see reference to function template instantiation 'boost::function0<R>::function0<void*>(Functor,int)' being compiled
2>          with
2>          [
2>              R=void,
2>              Functor=void *
2>          ]
2>          Test.cpp(61) : see reference to function template instantiation 'boost::function<Signature>::function<void*>(Functor,int)' being compiled
2>          with
2>          [
2>              Signature=void (void),
2>              Functor=void *
2>          ]
2>
2>Build FAILED.

(Test.cpp的第61行是add方法的最后一个)

更新2 :执行此操作后,它会构建并运行正常:

void Wrapper::ManagedEvent::add( Action^ managedEventHandler ){
    m_dManagedEvent += managedEventHandler;
    void(__stdcall*pTrampoline)() = static_cast<void(__stdcall*)()>( Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate( managedEventHandler ).ToPointer() );
    m_pNativeInstance->registerEventCallback( boost::function<void()>(pTrampoline) );
}

1 个答案:

答案 0 :(得分:2)

是。你已经拥有的东西。

GetFunctionPointerForDelegate创建一个包含this指针的蹦床,因此不需要boost::bind

唯一会改变的是,不是传递一个普通的函数指针,而是传递一个boost::function仿函数。转换应该是隐式的,您的C ++ / CLI代码不需要更改。

此外,在你爱上Boost之前,看看std::function类,它有许多新的C ++ 11功能。