问题
I have a situation where I have to pass a struct to a C method (declared as extern in my C# file).
This struct however is quite complicated. I already used successfully the approach with AllocHGlobal, but I would like to understand if is possible to make it works in this way, by only passing a reference to the struct.
[StructLayout(LayoutKind.Sequential)]
struct lgLcdBitmapHeader
{
public Formats Format;
}
[StructLayout(LayoutKind.Explicit)]
struct lgLcdBitmap
{
[FieldOffset(0)]
public lgLcdBitmapHeader hdr;
[FieldOffset(0)]
public lgLcdBitmap160x43x1 bmp_mono;
[FieldOffset(0)]
public lgLcdBitmapQVGAx32 bmp_qvga32;
}
[StructLayout(LayoutKind.Sequential)]
struct lgLcdBitmap160x43x1 : IDisposable
{
/// <summary>
/// Format = LGLCD_BMP_FORMAT_160x43x1
/// </summary>
public lgLcdBitmapHeader hdr;
/// <summary>
/// byte array of size LGLCD_BMP_WIDTH * LGLCD_BMP_HEIGHT, use AllocHGlobal to make code safe
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)BWBitmapSizes.Size)]
internal byte[] pixels;
}
[StructLayout(LayoutKind.Sequential)]
struct lgLcdBitmapQVGAx32 : IDisposable
{
/// <summary>
/// Format = LGLCD_BMP_FORMAT_160x43x1
/// </summary>
public lgLcdBitmapHeader hdr;
/// <summary>
/// byte array of size LGLCD_QVGA_BMP_WIDTH * LGLCD_QVGA_BMP_HEIGHT * LGLCD_QVGA_BMP_BPP, use AllocHGlobal to make code safe
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)QVGABitmapSizes.Size)]
internal byte[] pixels;
}
The biggest problem is that I have to wrap everything in a union (the lgLcdBitmap struct). Actually C# is complaning because there is an object at offset 0 that is not correctly aligned or overlaps another object.
I think that the problem is connected with the fact that my byte array doesn't have a real size (only the one declared with SizeConst). Because I don't want to use fixed (it forces me to use unsafe code), I would like to understand how can I solve this.
The only idea that I can think about is declaring Size (inside StructLayout) to allow C# understand what size is my struct, but I'm not sure it will works.
The method I have to call is this one:
public extern static uint lgLcdUpdateBitmap([In] int device, [In] ref lgLcdBitmap bitmap, [In] Priorities priority);
Any suggestion on how make everything works?
回答1:
Since you don't want to use fixed
, your byte arrays are best declared as IntPtr
, allocated with AllocHGlobal
and filled with data using Marshal.Copy
. There's no way to get the P/invoke marshaller to do what you need using MarshalAs
.
回答2:
If you don't need the union as such in managed code, don't make it a union. Declare two structs and two overloads of your p/invoke function.
来源:https://stackoverflow.com/questions/7627521/passing-a-struct-with-a-byte-array-inside-to-a-interop-ed-method