Страницы

Поиск по вопросам

пятница, 31 января 2020 г.

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

#c_sharp #net #unsafe


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

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



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


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

Структура DxgiRbg:

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

    /// 
    ///     A value representing the color of the green component. The range of this
value is between 0 and 1.
    /// 
    public float Green;

    /// 
    ///     A value representing the color of the blue component. The range of this
value is between 0 and 1.
    /// 
    public float Blue;
}




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

/// 
///     Controls the settings of a gamma curve.
/// 
public struct DxgiGammaControl
{
    /// 
    ///     A  structure with scalar values that are applied
to rgb values before being sent to the gamma
    ///     look up table.
    /// 
    public DxgiRgb Scale;

    /// 
    ///     A  structure with offset values that are applied
to the rgb values before being sent to the
    ///     gamma look up table.
    /// 
    public DxgiRgb Offset;

    /// 
    ///     An array of  structures that control the points
of a gamma curve.
    /// 
    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(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(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;
}


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

/// 
///     Controls the settings of a gamma curve.
/// 
public struct DxgiGammaControl
{
    /// 
    ///     A  structure with scalar values that are applied
to rgb values before being sent to the gamma
    ///     look up table.
    /// 
    public DxgiRgb Scale;

    /// 
    ///     A  structure with offset values that are applied
to the rgb values before being sent to the
    ///     gamma look up table.
    /// 
    public DxgiRgb Offset;

#pragma warning disable 649
    private GammaCurveStructArrayHelper _helper;
#pragma warning restore 649

    /// 
    ///     An array of  structures that control the points
of a gamma curve.
    /// 
    public DxgiRgb[] GammaCurve
    {
        get
        {
            _helper.ReadAllArrayData(out DxgiRgb[] arrayData);
            return arrayData;
        }

        set => _helper.WriteDataArray(value);
    }
}

    


Ответы

Ответ 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

Комментариев нет:

Отправить комментарий