unsafe структура с фиксированным массивом структур

130
28 декабря 2020, 07:20

Пробую перенести одну из структур с из DXGI, но столкнулся с проблемой.

Определение структуры

typedef struct DXGI_GAMMA_CONTROL {
  DXGI_RGB Scale;
  DXGI_RGB Offset;
  DXGI_RGB GammaCurve[1025];
} DXGI_GAMMA_CONTROL, *LPDXGI_GAMMA_CONTROL;

Хорошо, пробую перенести:

Структура DxgiRbg:

/// <summary>
///     Represents an RGB color.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct DxgiRgb
{
    /// <summary>
    ///     A value representing the color of the red component. The range of this value is between 0 and 1.
    /// </summary>
    public float Red;
    /// <summary>
    ///     A value representing the color of the green component. The range of this value is between 0 and 1.
    /// </summary>
    public float Green;
    /// <summary>
    ///     A value representing the color of the blue component. The range of this value is between 0 and 1.
    /// </summary>
    public float Blue;
}

Проблемная структура:

/// <summary>
///     Controls the settings of a gamma curve.
/// </summary>
public struct DxgiGammaControl
{
    /// <summary>
    ///     A <see cref="DxgiRgb" /> structure with scalar values that are applied to rgb values before being sent to the gamma
    ///     look up table.
    /// </summary>
    public DxgiRgb Scale;
    /// <summary>
    ///     A <see cref="DxgiRgb" /> structure with offset values that are applied to the rgb values before being sent to the
    ///     gamma look up table.
    /// </summary>
    public DxgiRgb Offset;
    /// <summary>
    ///     An array of <see cref="DxgiRgb" /> structures that control the points of a gamma curve.
    /// </summary>
    private unsafe fixed DxgiRgb GammaCurve[1025];
}

Проблема с определением поля

private unsafe fixed DxgiRgb GammaCurve[1025];

т.к. массивы фиксированной длины могут быть только из стандартных типов int, short, byte и т.д.

Как перенести такой массив кроме как выделением общего кол-ва байт под весь массив фиксированным полем?

fixed byte gammaCureve[Size_All_1025_Structs];

Ведь тут будут накладные расходы времени на вычисление позиции структур на основе их размеров и индекса который был запрошен.

Или завести стурктуру с общим объемом требуемой памяти и читать дынные из нее?

UPD:

Одно из придуманных мной извращений выглядит так:

Структура помощник:

[StructLayout(LayoutKind.Explicit, Size = 12300)]
internal unsafe struct GammaCurveStructArrayHelper
{
    internal DxgiRgb ReadById(int index)
    {
        fixed (GammaCurveStructArrayHelper* fixedThisPtr = &this)
        {
            IntPtr startData = new IntPtr(fixedThisPtr);
            return Marshal.PtrToStructure<DxgiRgb>(IntPtr.Add(startData,
                index * HelperDataGet.SizeStruct));
        }
    }
    internal void ReadAllArrayData(out DxgiRgb[] arrayDxgiRgb)
    {
        arrayDxgiRgb = new DxgiRgb[1025];
        for (int i = 0; i < 1025; i++) ReadOutWithId(i, out arrayDxgiRgb[i]);
    }
    internal void ReadOutWithId(int index, out DxgiRgb dxgiRgb)
    {
        fixed (GammaCurveStructArrayHelper* fixedThisPtr = &this)
        {
            IntPtr startData = new IntPtr(fixedThisPtr);
            dxgiRgb = Marshal.PtrToStructure<DxgiRgb>(IntPtr.Add(startData,
                index * HelperDataGet.SizeStruct));
        }
    }
    internal void WriteDataById(int index, DxgiRgb dxgiRgb)
    {
        fixed (GammaCurveStructArrayHelper* fixedThisPtr = &this)
        {
            IntPtr writeIdPtr = IntPtr.Add(new IntPtr(fixedThisPtr), index * HelperDataGet.SizeStruct);
            IntPtr rgbPtr = new IntPtr(&dxgiRgb);
            Marshal.Copy(rgbPtr, new[] {writeIdPtr}, 0, HelperDataGet.SizeStruct);
        }
    }
    internal void WriteDataArray(DxgiRgb[] array)
    {
        if (array == null) throw new ArgumentNullException(nameof(array));
        if (array.Length < 1025 || array.Length > 1025)
            throw new ArgumentException(
                "Writable array cannot be greater than 1025 element and less than 1025 elements!",
                nameof(array));
        for (int i = 0; i < 1025; i++) WriteDataById(i, array[i]);
    }
}
internal struct HelperDataGet
{
    internal const int SizeStruct = 12;
}

И реализация чтения/записи:

/// <summary>
///     Controls the settings of a gamma curve.
/// </summary>
public struct DxgiGammaControl
{
    /// <summary>
    ///     A <see cref="DxgiRgb" /> structure with scalar values that are applied to rgb values before being sent to the gamma
    ///     look up table.
    /// </summary>
    public DxgiRgb Scale;
    /// <summary>
    ///     A <see cref="DxgiRgb" /> structure with offset values that are applied to the rgb values before being sent to the
    ///     gamma look up table.
    /// </summary>
    public DxgiRgb Offset;
#pragma warning disable 649
    private GammaCurveStructArrayHelper _helper;
#pragma warning restore 649
    /// <summary>
    ///     An array of <see cref="DxgiRgb"/> structures that control the points of a gamma curve.
    /// </summary>
    public DxgiRgb[] GammaCurve
    {
        get
        {
            _helper.ReadAllArrayData(out DxgiRgb[] arrayData);
            return arrayData;
        }
        set => _helper.WriteDataArray(value);
    }
}
Answer 1
[StructLayout(LayoutKind.Sequential)]
public struct DxgiGammaControl {
    public DxgiRgb Scale;
    public DxgiRgb Offset;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1025)]
    public DxgiRgb[] GammaCurve;
}

https://docs.microsoft.com/ru-ru/dotnet/framework/interop/default-marshaling-for-arrays#arrays-within-structures

READ ALSO
Как получить список всех элементов на странице из WebBrowser?

Как получить список всех элементов на странице из WebBrowser?

Как получить список всех элементов на странице из элемента управления WebBrowser? Необходимо получить именно всех элементов, а не отдельные из них

132
Ссылка на объект не указывает на экземпляр объекта при сбросе combobox [дубликат]

Ссылка на объект не указывает на экземпляр объекта при сбросе combobox [дубликат]

Есть код, который выводит строки в datagridview при выборе индекса из comboboxНо при сбросе через comboBox1

119
Переход к заданной позиции в файле

Переход к заданной позиции в файле

Мне нужно считывать символы с указанной позиции(lastIndexChangedSymbol), что бы вернуться в начало предложения, тк

143
Ошибка при запуске проекта avalonia.mvvm .net core

Ошибка при запуске проекта avalonia.mvvm .net core

Создаю проект по шаблону avaloniamvvm (Avalonia UI) на

117