替换带有成员函数的自由函数原生回调函数我拥有由C++/CLI类包装的本地C++类,以便C#类可以使用它们。讨厌,但工作。到目前为止,映射本地回调来我做了这样的事情在我的包装类.NET事件:使用boost :: bind
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
是System::Action^
- 本地回调定义为免费的功能;在这种情况下,
typedef void __stdcall NativeCallback();
,内部INativeInterface
。
这工作正常,但现在我爱上了Boost,这意味着使用boost::function
和boost::bind
。这在原生类之间很好,但是假设我想改变我的 registerEventCallback
函数,以便它收到boost::function<void()>
。我将如何改变add
和remove
方法?
我想到了这一点,但它迫使我写的每个事件的另一个成员函数,我不知道它甚至会因为建设是this
跟踪句柄:
void Wrapper::FireManagedEvent(){
m_dManagedEvent();
}
void Wrapper::ManagedEvent::add(Action^ managedEventHandler){
m_dManagedEvent += managedEventHandler;
m_pNativeInstance->registerEventCallback(boost::bind(&Wrapper::FireManagedEvent, this));
}
有没有更好的解决办法?
更新:每@Ben福格特的回答,我试过如下:
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:这样做,它建立和运行OK:
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));
}
它不编译,看我更新的问题。我也尝试过'reinterpret_cast'并得到了一个不同的错误。 – 2012-02-10 12:51:09
我修正了它,看起来像一个调用约定的事情:它看起来像C++/CLI在默认情况下使用__cdecl,并且涉及__stdcall的显式强制转换是必要的。查看问题的最后更新。现在它编译并正常工作。请告诉我,如果有更优雅的方式,或者我没有注意到的一些陷阱。 – 2012-02-10 13:05:02
@dario:我不确定,但我认为你需要使用'__cdecl'来兼容'std :: function'和'boost :: function'。通过在托管代理类型上指定“CallingConvention :: Cdecl”,可以使'GetFunctionPointerForDelegate'返回'void(__ cdecl *)()'。 – 2012-02-10 13:17:52