Search code examples
c#.netcommarshallingcom-interop

Marshal [in] reference without ref


Some functions, especially in COM interfaces, expose a REFIID parameter that is used to specify the type of the interface the methods should return. Here's such an example method:

[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);

The fourth parameter is input-only, and should not be changed by SHBindToObject, so by C# conventions, it makes no sense passing it as a reference (aside from performance). I can't recall it clearly, but I remember that there should be some custom attribute or something that is designated for this case, to tell the marshaller that it should be really marshalled as if it were ref Guid, while it is specified without ref in the signature.

I looked for attributes in the System.Runtime.InteropServices names, fields on MarshalAsAttribute, and in the UnmanagedType enum, but without success.

Does there happen to be something similar, or is my memory incorrect? Is it good using such a thing in this case?


Solution

  • You're looking for 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);