Передача структуры с байтовым массивом внутри взаимодействующему методу - PullRequest
0 голосов
/ 02 октября 2011

У меня есть ситуация, когда я должен передать структуру в метод C (объявлен как extern в моем файле C #).

Эта структура, однако, довольно сложна. Я уже успешно использовал подход с AllocHGlobal, но я хотел бы понять, возможно ли заставить его работать таким образом, только передавая ссылку на структуру.

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

Самая большая проблема заключается в том, что мне нужно обернуть все в объединение (структура lgLcdBitmap). На самом деле C # комплируется, потому что есть объект со смещением 0, который неправильно выровнен или перекрывает другой объект.

Я думаю, что проблема связана с тем фактом, что мой байтовый массив не имеет реального размера (только тот, который объявлен с SizeConst). Поскольку я не хочу использовать исправленный (это заставляет меня использовать небезопасный код), я хотел бы понять, как я могу решить эту проблему.

Единственная идея, о которой я могу подумать, - это объявить Size (внутри StructLayout), чтобы C # мог понять, какой размер моей структуры, но я не уверен, что он будет работать.

Я должен вызвать метод:

public extern static uint lgLcdUpdateBitmap([In] int device, [In] ref lgLcdBitmap bitmap, [In] Priorities priority);

Любое предложение о том, как сделать все работает?

Ответы [ 2 ]

1 голос
/ 02 октября 2011

Если вам не нужно объединение как таковое в управляемом коде, не делайте его объединением. Объявите две структуры и две перегрузки вашей функции p / invoke.

0 голосов
/ 02 октября 2011

Поскольку вы не хотите использовать fixed, ваши байтовые массивы лучше всего объявлять как IntPtr, выделять с помощью AllocHGlobal и заполнять данными с использованием Marshal.Copy.Нет способа заставить маршаллера P / invoke делать то, что вам нужно, используя MarshalAs.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...