我有一个具有树重要功能的原生API,CreateObject
,DestroyObject
和CloneObject
,并且CreateObject
期望一个函数指针,我绑定到某些{托管代码中的{1}}:
NativeDelegate
然后,我在托管代码中为本地生活的对象创建了一个代理,如下所示:
[UnmanagedFunctionPointer]
public delegate double NativeDelegate(double);
internal static class NativeInterop
{
[DllImport("native.dll", EntryPoint="CreateObject")]
public static extern IntPtr CreateObject(NativeDelegate fctn);
[DllImport("native.dll", EntryPoint="DestroyObject")]
public static extern void DestroyObject(IntPtr pa);
[DllImport("native.dll", EntryPoint="CloneObject")]
public static extern IntPtr CloneObject(IntPtr pa);
}
NB:对于我到目前为止所做的测试,这一切都很好。 对我来说唯一的诀窍是保持构造函数的委托活着,因为它可能不再在托管代码中被引用,同时仍被其他本机API调用通过代理使用(未在示例代码中报告) )
现在我想知道如何克隆这个代理。目前我正在考虑:
public class NativeObject : IDisposable
{
public NativeObject(NativeDelegate fctn)
{
pa = NativeInterop.CreateObject(fctn);
keepAlive = fctn; // Because delegate may no longer be referenced anywhere else in managed code.
}
public Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void dispose(bool disposing)
{
if (pa == IntPtr.Zero) { return; }
NativeInterop.DestroyObject(pa);
pa = IntPtr.Zero;
}
~NativeObject()
{
Dispose(false);
}
private NativeDelegate keepAlive;
private IntPtr pa;
}
我有点自信这是可以的......但不知怎的,我也在蛋壳上行走......你能否证实我克隆代理是这样的,我不会陷入竞争状态我已经避风港了还没想到呢?是否可以制作代理的表面副本,即使是lambda,lambda引用本地范围变量?。
例如:
public NativeObject Clone()
{
if (pa == IntPtr.Zero) { throw new InvalidOperationException("Already disposed"); }
var _pa = NativeInterop.CloneObject(pa); // Ask native API to make deep-copy on its side
var _keepAlive = keepAlive; // Make shallow copy only for the delegate
return new NativeObject(_pa, _keepAlive);
}
private NativeObject(IntPtr pa, NativeDelegate keepAlive)
{
this.pa = pa;
this.keepAlive = keepAlive;
}