【问题标题】:Can PInvoke convert [out] parameter into return value?PInvoke 可以将 [out] 参数转换为返回值吗?
【发布时间】:2014-06-06 08:47:05
【问题描述】:

我是 PInvoke 的新手,需要一些帮助。

我想使用 PInvoke 访问 IEnumGUID,我在 pinvoke.net 上找到了一个代码块。

 [ComImport, Guid("0002E000-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComVisible(false)]
 public interface IEnumGUID
 {
     int Next(int celt, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)]Guid[] rgelt);
     void Skip(int celt);
     void Reset();
     [return: MarshalAs(UnmanagedType.Interface)]
     IEnumGUID Clone();
 }

这里的 Clone 函数将 IEnumGUID 作为返回值,而the function in the the original C++ interface 将其作为输出参数

HRESULT Clone(
  [out]  IEnumGUID **ppenum
);

我了解到 PInvoke 会自动将 HRESULT 转换为 COMException,但我不知道 PInvoke 如何将 out 参数 转换为 返回值

请对此进行一些解释,以便我以后可以正确使用此方法。

【问题讨论】:

    标签: c# pinvoke


    【解决方案1】:

    pinvoke.net 网站并不完美。它有很多错误,与任何人在其代码中使用该声明的可能性成反比。这个概率很低,你发现的声明被严重破坏了。

    这与 pinvoke 无关,COM 互操作是 .NET 中的一个显着特性。将参数转换为返回值的能力高度特定于 COM 自动化,并且高度特定于使用 [out, retval] 属性修饰的参数。正是 [retval] 向 COM 客户端运行时支持库提供了参数可以被视为返回值的提示。很常见,例如,任何脚本语言都会利用这一点。任何 .NET 语言也是如此,除非使用 [PreverseSig] 属性显式禁止转换。

    IEnumGUID::Clone() 的参数没有 [retval] 属性,因此不应像它那样声明。这不是唯一的错误,其他成员需要 [PerserveSig] 属性,因为您需要知道它们的返回值才能正确使用它们。正确的声明是:

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0002E000-0000-0000-C000-000000000046")]
    public interface IEnumGUID
    {
        [PreserveSig]
        int Next(int celt, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Guid[] rgelt, out int pceltFetched);
        [PreserveSig]
        int Skip(int celt);
        [PreserveSig]
        int Reset();
        void Clone(out IEnumGUID ppenum);
    }
    

    COM IEnumXxxx 接口非常常见,仅通过枚举器返回的元素类型来区分。其中一些存在于 .NET Framework 中,例如与 this one 相比。

    【讨论】:

    • 太棒了!感谢您告诉我有关 [retval] 的信息,并更正声明!顺便说一句,MSDN 文档说 Next、Skip、Reset 函数都返回 HRESULT。他们是在说错误的信息吗? msdn.microsoft.com/en-us/library/windows/desktop/…
    • 我记错了。更正了,它实际上只对 Next() 至关重要。你需要知道什么时候没有下一个。
    • 我明白了!你帮了我很多。谢谢你:)
    • 为什么不能是一个没有 [retval] 使用返回编组的函数?属性毕竟只是一个提示不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 2011-10-24
    相关资源
    最近更新 更多