C# PInvoke能否将[out]参数转换为返回值?

C# PInvoke能否将[out]参数转换为返回值?,c#,pinvoke,C#,Pinvoke,我是PInvoke的新手,我需要一些帮助 我想使用PInvoke访问IEnumGUID,我在上发现了一个代码块 这里的Clone函数将IEnumGUID作为返回值,而将其作为out参数 我了解到PInvoke会自动将HRESULT转换为COMException,但我不知道PInvoke如何将out参数转换为返回值 请对此做一些解释,以便我以后能正确使用此方法。pinvoke.net网站并不完美。它有很多错误,与任何人在代码中使用声明的可能性成反比。这一次的几率很低,你发现的声明被严重破坏了 这与

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

我想使用PInvoke访问IEnumGUID,我在上发现了一个代码块

这里的Clone函数将IEnumGUID作为返回值,而将其作为out参数

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


请对此做一些解释,以便我以后能正确使用此方法。

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接口非常常见,仅通过枚举器返回的元素类型来区分。例如,与pinvoke.NET网站相比,.NET框架中有几个网站是存在的。

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中,与之相比,例如。

太棒了!感谢您告诉我有关[retval]的信息,并更正声明!顺便说一句,MSDN文档说Next、Skip、Reset函数都返回HRESULT。他们说的是错误的信息吗?我记错了。更正后,它实际上只对Next()至关重要。你需要知道什么时候没有下一个。我明白了!你帮了我很多。谢谢:)为什么没有使用返回进行编组的
[retval]
就不能成为函数?这个属性毕竟只是一个暗示,不是吗?太好了!感谢您告诉我有关[retval]的信息,并更正声明!顺便说一句,MSDN文档说Next、Skip、Reset函数都返回HRESULT。他们说的是错误的信息吗?我记错了。更正后,它实际上只对Next()至关重要。你需要知道什么时候没有下一个。我明白了!你帮了我很多。谢谢:)为什么没有使用返回进行编组的
[retval]
就不能成为函数?这个属性毕竟只是一个暗示,不是吗?
[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);
}