Как избежать копирования во время маршалинга PInvoke, когда структура содержит массив целых чисел? - PullRequest
1 голос
/ 24 февраля 2012

У меня есть структура "C", которая определяется как:

typedef unsigned char tUI8;

typedef struct
{
    tUI8 Mode;
    tUI8 Data[16];
} TestStruct;

И функция, которая берет указатель на эту структуру и заполняет данные:

void FillTest(tUI8 Mode, TestStruct *s);

Чтобы вызвать эту функцию, я написал код C # как:

[StructLayout(LayoutKind.Sequential)]
struct TestStruct
{
    public byte Mode;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] Data;
}

static class NativeTest
{
    [DllImport("Native.dll")]
    public static extern void FillTest(byte mode, ref TestStruct s);
}

Это работает, но я подозреваю, что во время PInvoke маршаллер копирует структуру во время вызова и возврата вместо закрепления. Я могу сказать это, потому что даже если я не инициализирую структуру, она отлично работает.

TestStruct s;
//here s.Data == null!
NativeTest.FillTest(10, ref s); //<<< I expected an error here
//here s.Data points to a valid byte[] of length 16
Console.WriteLine(BitConverter.ToString(s.Data));

У меня вопрос: как определить сигнатуру PInvoke, используя структуру или класс, чтобы избежать копирования данных во время маршалинга?

Ответы [ 2 ]

2 голосов
/ 24 февраля 2012

Я подозреваю, что вам нужен буфер фиксированного размера , который будет вставлять данные в вашу структуру:

[StructLayout(LayoutKind.Sequential)]
unsafe struct TestStruct
{
    public byte Mode;
    public fixed byte Data[16];
}

Теперь вы сможете передавать это по ссылке непосредственно на ваш неуправляемый код. (Вам также необходимо явно разрешить небезопасный код.)

Я не знаю, какие атрибуты вам понадобятся для сортировки, если таковые имеются, но стоит попробовать ...

0 голосов
/ 22 февраля 2016

Это можно сделать без использования небезопасного кода.

С помощью команды ByValArray

[StructLayout(LayoutKind.Sequential)]
struct TestStruct
{
    public byte Mode;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] Data;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...