Reputation: 137467
C definitions
typedef struct {
const uint8_t* buf;
int bufLen;
} Info;
int Foo(Info* info);
C# definitions
[StructLayout(LayoutKind.Sequential)]
public struct Info
{
// [MarshalAs( ??? )]
public byte[] buf;
int bufLen
}
[DllImport(...)]
public static extern int Foo(ref Info info);
I'm having trouble figuring out what to specify for the MarshalAs
attribute on byte[] buf
in the C# struct definition. The buffer is allocated on the .NET side, and its length is known at call time.
In a simple little test:
var info = new Info {
buf = new byte[] {0x40, 0x50, 0x60, 0x70},
bufLen = 4,
};
Foo(ref info);
Everything seems to be working correctly, but in fact the data in my buffer is incorrect. Printing it out from the DLL I see 01 00 80 00
- not sure what that is.
I've tried:
MarshalAs
[MarshalAs(UnmanagedType.SafeArray)]
and nothing works.
In general, I really don't know the best way to debug these kinds of problems either.
Upvotes: 5
Views: 2870
Reputation: 89
I know it is too late.. but just in case if some one come here for an answer.
I finally came up with next solution for similar exercise.
[StructLayout(LayoutKind.Sequential)]
public struct Info
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] buf;
int bufLen
}
From MSDN
Arrays can be marshaled as UnmanagedType.ByValArray, which requires you to set the MarshalAsAttribute.SizeConst field. The size can be set only as a constant.
In my case the buffer size is 8 bytes.
Upvotes: 0
Reputation: 137467
Per Hans Passant's suggestion, I implemented the following:
[StructLayout(LayoutKind.Sequential)]
public struct Info : IDisposable
{
private IntPtr buf;
private int bufLen;
public Info(byte[] buf) : this() {
this.buf = Marshal.AllocHGlobal(buf.Length);
Marshal.Copy(buf, 0, this.buf, buf.Length);
this.bufLen = buf.Length;
}
public void Dispose() {
if (buf != IntPtr.Zero) {
Marshal.FreeHGlobal(buf);
buf= IntPtr.Zero;
}
}
}
Upvotes: 4