我有很多本机类都接受某种形式的回调,通常是boost::signals2::slot
-object。
但是为了简单起见,让我们假设该类:
class Test
{
// set a callback that will be invoked at an unspecified time
// will be removed when Test class dies
void SetCallback(std::function<void(bool)> callback);
}
Run Code Online (Sandbox Code Playgroud)
现在,我有一个包装了该本机类的托管类,并且我想将回调方法传递给本机类。
public ref class TestWrapper
{
public:
TestWrapper()
: _native(new Test())
{
}
~TestWrapper()
{
delete _native;
}
private:
void CallbackMethod(bool value);
Test* _native;
};
Run Code Online (Sandbox Code Playgroud)
现在通常我会执行以下操作:
看起来像这样:
_managedDelegateMember = gcnew ManagedEventHandler(this, &TestWrapper::Callback);
System::IntPtr stubPointer = Marshal::GetFunctionPointerForDelegate(_managedDelegateMember);
UnmanagedEventHandlerFunctionPointer functionPointer = static_cast<UnmanagedEventHandlerFunctionPointer >(stubPointer.ToPointer());
_native->SetCallback(functionPointer);
Run Code Online (Sandbox Code Playgroud)
我想减少代码量,而不必执行任何强制类型转换或声明任何委托类型。我想使用没有委托的lambda表达式。
这是我的新方法:
static void SetCallbackInternal(TestWrapper^ self)
{
gcroot<TestWrapper^> instance(self);
self->_native->SetCallback([instance](bool value)
{
// access managed class from within native code
instance->Value = value;
}
);
}
Run Code Online (Sandbox Code Playgroud)
this
可以使用C ++ 11 lambda 接受的静态方法。问题:
这种方法安全吗?我担心我会丢失某些东西,并且在某些无法预料的情况下,这会导致内存泄漏/不确定的行为。
编辑:
MethodAccessException
当lambda调用其托管包装器类的私有方法时,此方法会导致。看来这种方法至少必须是internal
。
在我的整个代码库中用这个新方法替换旧方法后,我可以报告它是安全的,更简洁,并且据我所知,没有发生内存泄漏。
因此,我强烈推荐这种将托管回调传递给本机代码的方法。
我发现的唯一警告如下:
internal
,以免MethodAccessException
在调用时抛出异常。这是有道理的,因为它不是在类范围本身内调用的。但 C# 的委托/lambda 仍然没有这个限制。 归档时间: |
|
查看次数: |
138 次 |
最近记录: |