【问题标题】:Marshal [in] reference without refMarshal [in] 没有参考的参考
【发布时间】:2018-02-13 16:30:00
【问题描述】:

某些函数,尤其是在 COM 接口中,会公开一个 REFIID 参数,该参数用于指定方法应返回的接口类型。这是一个示例方法:

[DllImport("shell32.dll", PreserveSig=false)]
[return: MarshalAs(UnmanagedType.IUnknown)]
static extern object SHBindToObject(IShellFolder psf, IntPtr pidl, [MarshalAs(UnmanagedType.IUnknown)]object pbc, [In]ref Guid riid);

第四个参数仅用于输入,不应被SHBindToObject 更改,因此按照 C# 约定,将其作为引用传递是没有意义的(除了性能之外)。我记不清了,但我记得应该有一些自定义属性或为这种情况指定的东西,告诉编组器应该像ref Guid一样真正编组它,而它没有指定签名中的ref

我在 System.Runtime.InteropServices 名称、MarshalAsAttribute 上的字段和 UnmanagedType 枚举中查找属性,但没有成功.

是否有类似的事情发生,或者我的记忆不正确?在这种情况下使用这样的东西好吗?

【问题讨论】:

  • 如果结构很大,在 C 和 C++ 代码中通过引用传递结构是一种非常常见的做法。它避免了编译器创建它的副本,这在大型结构上变得昂贵。在 C# 中也是一个好主意,尽管众所周知在 C# 中声明大型结构是不明智的。理想情况下,这样的论点使用const 限定符,但对它的支持参差不齐。就像在 C# 中一样。使用ref Guid 很好,并且可以避免编组器创建副本。您可能会要求这样做以避免与 Guid 争吵,以便它可以与 ref 一起传递,这从 C# v4 开始就没有必要了。
  • 从 C# 7.2 开始,您可以使用 in 参数修饰符进行更简单的声明。 ... pbc, in Guid riid);

标签: c# .net com marshalling com-interop


【解决方案1】:

您正在寻找MarshalAs(UnmanagedType.LPStruct):

[DllImport("shell32.dll")]
[return: MarshalAs(UnmanagedType.IUnknown)]
static extern object SHBindToObject(
    IShellFolder psf,
    IntPtr pidl, 
    [MarshalAs(UnmanagedType.IUnknown)] object pbc,  
    [MarshalAs(UnmanagedType.LPStruct)] Guid riid);

【讨论】:

  • 啊,当然。 MSDN 文档严重缺乏有关此值的适当信息。这也适用于 COM 方法,尽管我希望可以使用 Guid 以外的其他类型。
  • 好吧,事实证明,在 COM 导入接口中调用方法时,您不必指定 ref。这不是我所期望的。
  • @IllidanS4 - Microsoft 从 .NET 4 开始使用 COM 互操作简化了很多事情(IDispatch 调用的动态关键字、自动引用参数、可选参数等)。一个原因是为了简化 Office 自动化,例如 Word 方法有几十个可选的 ref 参数,它们在 .NET 中并不是超级实用...
猜你喜欢
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-13
  • 1970-01-01
  • 1970-01-01
  • 2013-05-01
  • 1970-01-01
相关资源
最近更新 更多