替換帶有成員函數的自由函數原生回調函數我擁有由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