How do I marshal a structure as a pointer to a structure?
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.

THX-1138
Updated on June 04, 2022Comments
-
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 over 13 yearsYou don't even need the [MarshalAs] in this case I think.
-
THX-1138 over 13 yearsEnd 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 over 5 yearsIsn't
[In] ref
better thanref
because the marshaler won't bother copying back? -
jnm2 over 5 yearsBtw, thanks for the explanation of why this is so. That's what I really wanted.
-
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?)