C# 在哪些情况下,执行P/Invoke调用时应固定参数

C# 在哪些情况下,执行P/Invoke调用时应固定参数,c#,interop,pinvoke,C#,Interop,Pinvoke,我有一个DLL,需要从中p/调用以下C方法: int DAOpen(HANDLE *hOpen, UNIT *flags, void *callback, char *userData) 我想出了以下C#签名: [DllImportAttribute("<libName>", EntryPoint="DAOpen")] static extern int DAOpen( out IntPtr hOpen,

我有一个DLL,需要从中p/调用以下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);
[DllImportAttribute(“,EntryPoint=“DAOpen”)]
静态外部int DAOpen(
霍本国际酒店,
参考uint标志,
IntPtr回调,
IntPtr用户数据);
假设本机代码将对所有参数的引用保留的时间长于p/Invoke调用的持续时间:

  • 除了保留一个hOpen的
    实例之外,我还应该锁定它吗

  • 我应该保留
    标志
    变量的引用吗?在这个特殊情况下,它作为引用传递,我是否也应该将其固定

  • 我正在按以下方式分配我的
    回调
    委托:

    private IntPtr callBackOnNativeEvents

    this.callBackOnNativeEvents=Marshal.GetFunctionPointerForDelegate(

    新回调(this.CallBackOnNativeEvents))

    我是否应该保留对委托本身的引用(而不仅仅是指针)?我应该也别针吗

  • 最后,我用以下方式定义
    userData
    参数:

    私有IntPtr用户数据

    string userName=“test”
    this.userData=Marshal.StringToHGlobalAnsi(用户名)

    我应该保留对字符串的引用吗?我应该也别针吗?API文档声明它将字符串内容复制到非托管内存,但我不确定它是否复制了引用的内容

  • 不需要pin
    hOpen
    ,它具有值类型语义
  • 如果DLL写入到由
    标志
    指向的地址,并且在原始函数返回后这样做,那么您需要以某种方式固定它(以及保持它的活动性和安全性,不受GC的控制)
  • 回调函数指针已被有效固定。您需要保持对委托的引用处于活动状态,但不需要固定它,因为
  • 您不需要在此处执行任何特殊操作,因为您正在传递一个
    IntPtr
    ,而它后面的内存被固定。您不需要保持对字符串的引用处于活动状态,因为它与
    StringToHGlobalAnsi
    返回的
    IntPtr
    完全断开。它只是在调用
    StringToHGlobalAnsi
    时有一个字符串内容的副本

  • 我不得不说,我仍然不相信这个DLL真的能像你说的那样。我怀疑还有什么地方出了问题,您错误地诊断为DLL持有一个调用中的指针参数,然后在后续调用中修改其内容。我觉得难以置信,但当然只有你才能真正知道。如果我处在您的位置,我只想问DLL供应商的问题。

    谢谢您的回答!正是我要找的。我会联系他们的,因为这确实是一种糟糕的形式。然而,这不会让我感到惊讶,因为他们在整个应用程序期间都会引用示例代码(C++)中的所有内容。。。委托不会被垃圾收集,因为我没有保留对它的引用吗?我保留了一个指向它的
    IntPtr
    ,但不是委托函数本身。我正在使用
    new
    动态创建它,作为
    GetFunctionPointerForDelegate
    函数的一个参数。@XenoAce您需要使代理保持活动状态,但无需担心固定问题。我在第3项中添加了一个链接来澄清这一点。啊,这就是我的想法。。。谢谢你澄清这一点!