Marshal :: GetFunctionPointerForDelegate:我应该发布它的结果吗?

时间:2013-05-13 15:55:33

标签: c# lambda c++-cli std-function

我正在将受管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?
}

3 个答案:

答案 0 :(得分:6)

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

请注意,委托对象不是这种情况,它受普通垃圾收集规则的约束。你必须要小心,thunk 让它保持活力。这是代码中的错误,可以在本机代码忙于执行时收集委托。您需要将这行代码添加到方法的末尾:

GC::KeepAlive(callback);

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

答案 1 :(得分:4)

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

答案 2 :(得分:2)

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