7

我正在将托管 System.Action 转换为 C++/CLI 项目中的非托管 std::function;我应该在使用回调后释放给定的 IntPtr,还是没有必要?

void MyClass::Execute(System::Action^ callback)
{           

    IntPtr callbackPtr = Marshal::GetFunctionPointerForDelegate(callback);
    std::function<void (void)> nativeCallback = static_cast<void (__stdcall *) (void)>(callbackPtr.ToPointer());

    m_nativeObject->Execute(wrappedCallback);

    // should I release callbackPtr here?
}
4

3 回答 3

7

不,没有 Marshal 类方法可以做到这一点。与所有动态生成的代码一样,此方法创建的 thunk 与 AppDomain 相关联,并在卸载 AppDomain 时被卸载。

请注意,委托对象并非如此,它受制于正常的垃圾收集规则。而且你必须小心,thunk 不会让它活着。这是您的代码中的一个错误,可以在本机代码忙于执行时收集委托。您需要将这行代码添加到方法的末尾:

GC::KeepAlive(callback);

假设只有在执行 Execute() 方法时才会进行回调。如果非托管代码在此方法调用之外存储函数指针,那么您必须将委托对象存储在某处以保持其有效。

于 2013-05-14T00:50:07.933 回答
4

不,但如果您调用 Alloc 在回调委托上创建 GCHandle,则必须使用 GCHandle.Free() 释放该句柄。这是一篇很好的文章,包括如何防止 GC 过早地处理您的委托:http: //msdn.microsoft.com/en-us/library/367eeye0%28v=VS.100%29.aspx

于 2013-05-13T16:05:15.627 回答
2

您无需释放指针。您已经有了指向该函数的指针(根据您的机器架构,它是 32/64 位大小)。如果 .net 框架基础结构需要更多的东西来运行指针,那么所有方法都将是相同的,因此它将被静态分配(无状态)。

于 2013-05-13T16:01:56.210 回答