[英]Replace free function native callback with member function using boost::bind
I have native C++ classes wrapped by C++/CLI classes so that C# classes can use them. 我有C ++ / CLI类包装的本机C ++类,因此C#类可以使用它们。 Nasty, but works.
讨厌,但有效。 So far, to map native callbacks to .NET events I did things like this in my wrapper classes:
到目前为止,为了将本机回调映射到.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_dManagedEvent
is a System::Action^
m_dManagedEvent
是一个System::Action^
typedef void __stdcall NativeCallback();
typedef void __stdcall NativeCallback();
, inside INativeInterface
. INativeInterface
。 This works fine, but now I fell in love with Boost, that means using boost::function
and boost::bind
. 这很好用,但现在我爱上了Boost,这意味着使用
boost::function
和boost::bind
。 That works great between native classes, but let's say I want to change my registerEventCallback
function so that it receives a boost::function<void()>
. 这在本机类之间很有效,但是我想说我想改变我的
registerEventCallback
函数,以便它接收一个boost::function<void()>
。 How would I have to change the add
and remove
methods? 我如何更改
add
和remove
方法?
I thought of this, but it forces me to write another member function per event, and I'm not sure it would even build because this
is a tracking handle: 我想到了这一点,但它迫使我为每个事件编写另一个成员函数,我不确定它是否会构建,因为
this
是一个跟踪句柄:
void Wrapper::FireManagedEvent(){
m_dManagedEvent();
}
void Wrapper::ManagedEvent::add( Action^ managedEventHandler ){
m_dManagedEvent += managedEventHandler;
m_pNativeInstance->registerEventCallback( boost::bind( &Wrapper::FireManagedEvent, this ) );
}
Is there a better solution? 有更好的解决方案吗?
Update : Per @Ben Voigt's answer, I tried the following: 更新 :根据@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() ) );
}
But it gives a compiler error: 但它给出了编译器错误:
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.
(Line 61 of Test.cpp is the last one of the add
method) (Test.cpp的第61行是
add
方法的最后一行)
Update 2 : Doing this, it builds and runs OK: 更新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) );
}
Yes. 是。 What you already have.
你已经拥有的。
GetFunctionPointerForDelegate
creates a trampoline containing the this
pointer, so there's no need for boost::bind
. GetFunctionPointerForDelegate
创建一个包含this
指针的trampoline,因此不需要boost::bind
。
The only thing that will change is instead of passing a plain function pointer, you'll pass a boost::function
functor. 唯一会改变的是传递一个普通的函数指针,你将传递一个
boost::function
仿函数。 The conversion should be implicit, your C++/CLI code won't need to change. 转换应该是隐式的,您的C ++ / CLI代码不需要更改。
Besides, before you fall too much in love with Boost, look at the std::function
class, it has many new capabilities with C++11. 此外,在你爱上Boost之前,看看
std::function
类,它有很多C ++ 11的新功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.