我有一个DLL,我需要P / Invoke以下C方法:
int DAOpen(HANDLE *hOpen, UNIT *flags, void *callback, char *userData)
我想出了以下C#签名:
[DllImportAttribute("<libName>", EntryPoint="DAOpen")]
static extern int DAOpen(
out IntPtr hOpen,
ref uint flags,
IntPtr callback,
IntPtr userData);
假设本机代码保留对所有参数的引用的持续时间超过P / Invoke调用的持续时间:
除了保留hOpen
的实例外,我还应该固定吗?
我应该保留flags
变量的引用吗?我是否也应该固定它,因为它在这种特殊情况下作为参考传递?
我是按照以下方式分配我的callback
代表:
private IntPtr callBackOnNativeEvents;
...
this.callBackOnNativeEvents = Marshal.GetFunctionPointerForDelegate(
new CallBack(this.CallBackOnNativeEvents));
我应该保留对委托本身的引用(不仅仅是指针)吗?我也应该把它钉住吗?
最后,我按以下方式定义userData
参数:
private IntPtr userData;
...
string userName = "test";
this.userData = Marshal.StringToHGlobalAnsi(userName);
我应该保留对字符串的引用吗?我也应该把它钉住吗? API文档声明它将字符串内容复制到非托管内存,但我不确定它是否复制了引用的内容。
答案 0 :(得分:2)
hOpen
,它具有值类型语义。flags
指向的地址,并且在原始函数返回后执行此操作,那么您需要以某种方式将其固定(以及保持其活着并且远离离合器GC)。IntPtr
并且后面的内存是固定的。您无需保持对字符串的引用,因为它与IntPtr
返回的StringToHGlobalAnsi
完全断开连接。它只是在调用StringToHGlobalAnsi
时的字符串内容的副本。我不得不说,我仍然不相信这个DLL真的可以做你说它正在做的事情。我怀疑你错误诊断的其他东西是错误的,因为DLL从一个调用中保留指针参数,然后在后续调用期间修改它们的内容。我觉得特别难以置信,但当然只有你才能真正了解。如果我在你的位置,我只会询问DLL供应商的问题。