How do I marshal a structure as a pointer to a structure?

19,289

Solution 1

Try passing the structure as a ref parameter.

[DllImport("MockVadavLib.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr TheFunction(ref UserRec userRec);

When you use a ref combined with a structure, it conceptually passes the address.

Solution 2

Incidentally, UnmanagedType.LPStruct is rarely, if ever, the correct MarshalAs argument. A quote from Adam Nathan who is a Microsoft employee:

UnmanagedType.LPStruct is only supported for one specific case: treating a System.Guid value type as an unmanaged GUID with an extra level of indirection.

Solution 3

Some additional information followup regarding @Rytmis's post.

From https://docs.microsoft.com/en-us/dotnet/standard/native-interop/best-practices#guids:


DO NOT Use [MarshalAs(UnmanagedType.LPStruct)] for anything other than ref GUID parameters.

Share:
19,289
THX-1138
Author by

THX-1138

Updated on June 04, 2022

Comments

  • THX-1138
    THX-1138 5 months

    I am trying to pass a structure from C# into C++ library. I pass structure as an object, and C++ function expects it as a pointer (void *).

    I am having problem passing the structure.

    [DllImport("MockVadavLib.dll", CharSet = CharSet.Ansi)]
    public static extern IntPtr TheFunction([MarshalAs(UnmanagedType.LPStruct)] UserRec userRec);
    

    Here is the run-time exception text I get:

    "Cannot marshal 'parameter #1': Invalid managed/unmanaged type combination (this value type must be paired with Struct)."

    Though I found an MSDN article that uses LPStruct in exactly this context.

    This is my structure I'm trying to marshal:

    [StructLayout(LayoutKind.Sequential)]
    public struct UserRec {
        [MarshalAs(UnmanagedType.I4)]
        public int userParam1;
    }
    

    This is C++ function:

    MOCKVADAVLIB_API tVDACQ_CallBackRec * TheFunction(void * userParams) {...
    
  • Anton Tykhyy
    Anton Tykhyy over 13 years
    You don't even need the [MarshalAs] in this case I think.
  • THX-1138
    THX-1138 over 13 years
    End working result: public static extern IntPtr TheFunction([MarshalAs(UnmanagedType.Struct), In] ref UserRec userRec); And [MurshalAs] here is just to make it explicit, but not required.
  • jnm2
    jnm2 over 5 years
    Isn't [In] ref better than ref because the marshaler won't bother copying back?
  • jnm2
    jnm2 over 5 years
    Btw, thanks for the explanation of why this is so. That's what I really wanted.
  • jnm2
    jnm2 over 5 years
    (Wait, what is this madness? I used ref in the signature but not at the call site! The C# language must have an exception for COM interfaces?)