Баг при передаче массива Com объекту

88
24 ноября 2021, 03:40

В общем я передаю массив структур объекту COM, и вроде бы все успешно происходит, но при запросе кол-ва переданных ему структур, этот объект возвращает 0. Т.е. ниже я продемонстрирую один из элементов IEntity:

public class ProgressBar
    : IEntity
{
    private readonly Stopwatch _stopwatch;
    private ColorF _backgroundColor;
    private ID2D1SolidColorBrush _backgroundColorBrush;
    private float _computedWidth;
    private RectF _cornerRect;
    private IDeviceResources _deviceResources;
    private long _elapsed;
    private ID2D1GradientStopCollection _gradientStopCollection;
    private ID2D1LinearGradientBrush _progressBrush;
    private RectF _progressRect;
    public ProgressBar(IDeviceResources deviceResources, int minValue = 0, int maxValue = 100)
    {
        _deviceResources = deviceResources;
        MinValue = minValue;
        MaxValue = maxValue;
        Value = 0;
        BackgroundColor = ColorF.White;
        ProgressColor = ColorF.SpringGreen;
        _stopwatch = new Stopwatch();
    }
    public int MaxValue { get; }
    public int MinValue { get; }
    public int Value { get; set; }
    public ColorF BackgroundColor
    {
        get { return _backgroundColor; }
        set { _backgroundColor = value; }
    }
    public ColorF ProgressColor { get; set; }
    public Point2F Position { get; set; }
    public RectF Margin { get; set; }
    public RectF Padding { get; set; }
    public SizeF Size { get; set; }
    public ref IDeviceResources DeviceResources
    {
        get { return ref _deviceResources; }
    }
    public void DiscardDeviceResources()
    {
        if (!(_progressBrush is null))
        {
            Marshal.ReleaseComObject(_progressBrush);
            _progressBrush = null;
        }
        if (!(_gradientStopCollection is null))
        {
            Marshal.ReleaseComObject(_gradientStopCollection);
            _gradientStopCollection = null;
        }
        if (!(_backgroundColorBrush is null))
        {
            Marshal.ReleaseComObject(_backgroundColorBrush);
            _backgroundColorBrush = null;
        }
    }
    public bool CreateDeviceResources()
    {
        if (!(_backgroundColorBrush is null) && !(_progressBrush is null) && !(_gradientStopCollection is null))
        {
            return true;
        }
        BrushProperties brushProperties =
            new BrushProperties(1.0f, in _deviceResources.WorldMatrix);
        int createSolidColorBrushResult = 0;
        if (_backgroundColorBrush is null)
        {
            createSolidColorBrushResult =
                _deviceResources
                    .RenderTarget
                    .CreateSolidColorBrush(in _backgroundColor, in brushProperties, out _backgroundColorBrush);
            if (0 != createSolidColorBrushResult)
            {
                return false;
            }
        }
        if (_gradientStopCollection is null)
        {
            GradientStop[] gradientStops =
            {
                new GradientStop(0.0f, ColorF.Red),
                new GradientStop(1.0f, ColorF.ForestGreen)
            };
            createSolidColorBrushResult =
                _deviceResources
                    .RenderTarget
                    .CreateGradientStopCollection
                    (
                        gradientStops,
                        (uint) gradientStops.Length,
                        Gamma.G22,
                        ExtendMode.Clamp,
                        out _gradientStopCollection
                    );
            if (0 != createSolidColorBrushResult)
            {
                Exception exception = Marshal.GetExceptionForHR(createSolidColorBrushResult);
                Debug.WriteLine($"[{nameof(CreateDeviceResources)}]: {exception.Message}", "ERROR");
                return false;
            }
            uint gradientStopCount = _gradientStopCollection.GetGradientStopCount();
            GradientStop[] stops = new GradientStop[gradientStopCount];
            _gradientStopCollection.GetGradientStops(stops, gradientStopCount);
        }
        LinearGradientBrushProperties gradientBrushProperties =
            new LinearGradientBrushProperties(new Point2F(.0f, .0f), new Point2F(150.0f, 150.0f));
        if (_progressBrush is null)
        {
            createSolidColorBrushResult =
                _deviceResources
                    .RenderTarget
                    .CreateLinearGradientBrush
                    (
                        in gradientBrushProperties,
                        in brushProperties,
                        _gradientStopCollection,
                        out _progressBrush
                    );
        }
        if (0 != createSolidColorBrushResult)
        {
            Exception exception = Marshal.GetExceptionForHR(createSolidColorBrushResult);
            Debug.WriteLine($"[{nameof(CreateDeviceResources)}]: {exception.Message}", "ERROR");
        }
        //_progressBrush.GetGradientStopCollection(out ID2D1GradientStopCollection gradientStopCollection);
        //gradientStopCollection.GetGradientStopCount();
        //Marshal.ReleaseComObject(gradientStopCollection);
        return 0 == createSolidColorBrushResult;
    }
    public void Update()
    {
        if (!_stopwatch.IsRunning)
        {
            _stopwatch.Start();
        }
        else
        {
            _elapsed = _stopwatch.ElapsedMilliseconds;
        }
        Value += _elapsed >= 1000
            ? Value < MaxValue
                ? 4
                : 0
            : 0;
        _computedWidth = Size.Width * 100.0f / (MaxValue * 100.0f / Value) - Margin.Right + Padding.Left - 1.0f;
        _cornerRect =
            new RectF
            (
                Position.X + Margin.Left - Padding.Left,
                Position.Y + Margin.Top - Padding.Left,
                Size.Width - Margin.Right + Padding.Right,
                Position.Y + Size.Height - Margin.Bottom + Padding.Bottom
            );
        _progressRect =
            new RectF
            (
                Position.X + Margin.Left - Padding.Left + 1.0f,
                Position.Y + Margin.Top - Padding.Top + 1.0f,
                _progressRect.Right < _computedWidth ? _progressRect.Right += .009f : _computedWidth,
                Position.Y + Size.Height - Margin.Bottom + Padding.Bottom - 1.0f
            );
    }
    public bool Render()
    {
        _deviceResources.RenderTarget.FillRectangle(in _cornerRect, _backgroundColorBrush);
        _deviceResources.RenderTarget.FillRectangle(in _progressRect, _progressBrush);
        if (_elapsed >= 1000)
        {
            _stopwatch.Restart();
        }
        return true;
    }
}

Где проблемным является метод bool CreateDeviceResources(), ну и для краткости метод который вызывается COM:

/// <summary>
///     A gradient stop collection represents a set of stops in an ideal unit length.
///     This is the source resource for a linear gradient and radial gradient brush.
/// </summary>
[Pure, PreserveSig]
new int CreateGradientStopCollection
(
    [In, MarshalAs(UnmanagedType.LPArray)]
    GradientStop[] gradientStops,
    uint gradientStopsCount,
    Gamma colorInterpolationGamma,
    ExtendMode extendMode,
    out ID2D1GradientStopCollection gradientStopCollection
);

Где его оригинал выглядит так:

/// <summary>
/// A gradient stop collection represents a set of stops in an ideal unit length.
/// This is the source resource for a linear gradient and radial gradient brush.
/// </summary>
/// <param name="colorInterpolationGamma">Specifies which space the color
/// interpolation occurs in.</param>
/// <param name="extendMode">Specifies how the gradient will be extended outside of
/// the unit length.</param>
STDMETHOD(CreateGradientStopCollection)(
    _In_reads_(gradientStopsCount) CONST D2D1_GRADIENT_STOP *gradientStops,
    _In_range_(>=,1) UINT32 gradientStopsCount,
    D2D1_GAMMA colorInterpolationGamma,
    D2D1_EXTEND_MODE extendMode,
    _COM_Outptr_ ID2D1GradientStopCollection **gradientStopCollection 
    ) PURE;

Так же в коде присутствует закоментированный код, которым я пытался так же получить данные из ID2D1GradientStopCollection что дало идентичный результат.

Как мне правильно передать этот массив структур в этот метод?

READ ALSO
Как правильно ограничить поворот gameObject в Unity

Как правильно ограничить поворот gameObject в Unity

У меня есть задача, ограничить движение по вертикали пушки от -20 до 20 градусов, если это значение превышается, то поворачивает платформа на которой...

268
Как управлять мышью ,а не курсором

Как управлять мышью ,а не курсором

Нужно глобально отслеживать и посылать движение и нажатие мыши и клавиатуры,чтобы программа управляла мышью абсолютно вездеПроблема в том...

211
async / await передача Task

async / await передача Task

Есть функция

71
С# WPF(MVVM) Как взаимодействовать с DependencyProperty из ViewModel

С# WPF(MVVM) Как взаимодействовать с DependencyProperty из ViewModel

Только недавно начал постигать паттерн MVVM, и столкнулся со следующим вопросомКак правильно получить доступ к DependencyProperty из ViewModel

88