【问题标题】:In which cases should parameters be pinned when performing a P/Invoke call在哪些情况下,执行 P/Invoke 调用时应固定参数
【发布时间】:2012-03-08 16:22:00
【问题描述】:

我有一个 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 调用的持续时间:

  1. 除了保留hOpen 的实例之外,我还应该固定它吗?

  2. 我应该保留flags 变量的引用吗?由于在这种特殊情况下它是作为参考传递的,我是否也应该固定它?

  3. 我通过以下方式分配我的callback 代表:

    private IntPtr callBackOnNativeEvents;
    ...
    this.callBackOnNativeEvents = Marshal.GetFunctionPointerForDelegate(
    new CallBack(this.CallBackOnNativeEvents));

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

  4. 最后,我通过以下方式定义userData 参数:

    private IntPtr userData;
    ...
    string userName = "test";
    this.userData = Marshal.StringToHGlobalAnsi(userName);

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

【问题讨论】:

    标签: c# interop pinvoke


    【解决方案1】:
    1. 无需固定hOpen,它具有值类型语义。
    2. 如果 DLL 写入由flags 指向的地址,并且在原始函数返回后这样做,那么您需要以一种或另一种方式固定它(以及保持它的活力和安全,使其免受GC)。
    3. 回调函数指针已被有效固定。您需要保持对代理的引用,但您不需要固定它,因为native thunk is allocated from the unmanged heap
    4. 你不需要在这里做任何特别的事情,因为你传递了一个IntPtr 并且后面的内存是固定的。您不需要保持对字符串的引用,因为它与StringToHGlobalAnsi 返回的IntPtr 完全断开连接。它只是在调用StringToHGlobalAnsi 时拥有字符串内容的副本。

    我不得不说我仍然不相信这个 DLL 真的可以做你所说的那样。我怀疑还有其他问题出现了,您将其误诊为 DLL 持有来自一次调用的指针参数,然后在后续调用期间修改它们的内容。我觉得这非常难以置信,但当然只有你才能真正知道。如果我处于你的位置,我只会问 DLL 供应商的问题。

    【讨论】:

    • 感谢您的回答!正是我要找的。我会联系他们,因为这确实是不好的形式。但是,这并不让我感到惊讶,因为他们在应用程序的整个持续时间内保留了对示例代码 (C++) 中所有内容的引用。
    • 关于第 3 点,我有点困惑……由于我没有保留对它的引用,所以不会对委托进行垃圾收集吗?
    • 我保留了一个 IntPtr 指向它,但不是委托函数本身。我正在使用new 动态创建它作为GetFunctionPointerForDelegate 函数的参数。
    • @XenoAce 您需要让代理保持活动状态,但您不必担心固定。我在第 3 项中添加了一个链接来阐明这一点。
    • 啊,这就是我的想法……感谢您澄清这一点!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 2022-01-14
    • 2014-02-07
    • 1970-01-01
    • 2014-07-29
    相关资源
    最近更新 更多