Массив фиксированного размера типа структуры - PullRequest
9 голосов
/ 02 ноября 2011

как мне объявить массив фиксированного размера типа структуры в C #:

[StructLayout(LayoutKind.Sequential,Pack=1), Serializable]
public unsafe struct MyStruct{
    ...
}

public class MyClass {
    ...
    public fixed MyStruct myStruct[256];
}

это приведет к CS1663: недопустимы буферы фиксированного размера типа структуры, как мне обойти это? Я предпочитаю не использовать тип C # или «структуру данных управляемой коллекции», так как мне часто приходится маршалировать это на нативный C ++

Ответы [ 2 ]

9 голосов
/ 02 ноября 2011

Если ваша структура C # использует только примитивные типы данных и имеет ту же структуру, что и ваша собственная структура в C ++, вы можете обойти эти ограничения с помощью ручного управления памятью и небезопасного кода. В качестве бонуса вы улучшите производительность, избегая сортировки.

Выделите память:

IntPtr arr = Marshal.AllocHGlobal (sizeof (MyStruct) * 256);

Это в основном malloc, поэтому выделенная память находится за пределами понимания GC.

Вы можете передать IntPtr нативному коду, как если бы он был MyStruct[256], и будет маршалироваться только IntPtr, а не память, на которую он указывает. Нативный и управляемый код могут напрямую обращаться к одной и той же памяти.

Для чтения / записи структур в массиве с C # используйте указатели C #:

static unsafe MyStruct GetMyStructAtIndex (IntPtr arr, int index)
{
    MyStruct *ptr = ((MyStruct *)arr) + index;
    return *ptr;
}

static unsafe void SetMyStructAtIndex (IntPtr arr, int index, MyStruct value)
{
    MyStruct *ptr = ((MyStruct *)arr) + index;
    *ptr = value;
}

Не забудьте

Marshal.FreeHGlobal (arr);

когда вы закончите с памятью, free это.

3 голосов
/ 02 ноября 2011

Вы не можете; по определению

Единственное ограничение: тип массива должен быть bool, byte, char, short, int, long, sbyte, ushort, uint, ulong, float или double.

...