Как получить базовый вектор IVector <IInspectable> - PullRequest
0 голосов
/ 06 января 2019

Я хочу использовать функцию, которая требует, чтобы я передавал ей в качестве параметра пустой указатель на начало блока памяти. Чтобы эта функция работала правильно, данные должны быть непрерывными в памяти.

Сейчас мои данные хранятся в IVector<IInspectable>. Глядя на схему памяти этого IVector в отладчике, я вижу, что между моими данными находится 28 байтов. Который я считаю 7 указателями функций из IUnknown и IInspectable. Как я могу получить основное непрерывное распределение памяти моих данных?

UPDATE : Вот решение, которое я придумал.

Вместо использования IVector<IInspectable> я создал собственный вектор, используя winrt::vector_base, как рекомендовано здесь: https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/collections и я обернул его в компонент времени выполнения Windows, чтобы я мог использовать этот собственный вектор из C #.

Это выглядит так:

MyVector.idl

namespace RuntimeComponent1
{
    [default_interface]
    runtimeclass MyVector 
    {
        MyVector();
        void Append(IInspectable in_val);
    }
}

MyVector.h

// MyVector.h
#pragma once

#include "MyVector.g.h"

namespace winrt::RuntimeComponent1::implementation
{
    using namespace winrt::Windows::Foundation;
    using namespace winrt::Windows::Foundation::Collections;

    struct _MyVector :
        implements<_MyVector, IVector<int>, IVectorView<int>, IIterable<int>>,
        winrt::vector_base<_MyVector, int>
    {
        auto& get_container() const noexcept
        {
            return m_values;
        }

        auto& get_container() noexcept
        {
            return m_values;
        }

    private:
        std::vector<int> m_values{};
    };

    struct MyVector : MyVectorT<MyVector, _MyVector>
    {
        MyVector() = default;
        void Append(Windows::Foundation::IInspectable const& in_val);
    };
}

namespace winrt::RuntimeComponent1::factory_implementation
{
    struct MyVector : MyVectorT<MyVector, implementation::MyVector>
    {
    };
}

MyVector.cpp

#include "pch.h"
#include "MyVector.h"

using namespace winrt;

namespace winrt::RuntimeComponent1::implementation
{
    void MyVector::Append(Windows::Foundation::IInspectable const& in_val)
    {
        base_type::Append(winrt::unbox_value<int>(in_val));
    }
}

Пример использования:

C #

MyRuntimeComponent.MyVector my_vec = new RuntimeComponent1.MyVector();
my_vec.Append(2);
my_vec.Append(4);

MyRuntimeComponent.MyControl my_control = new RuntimeComponent0.MyControl();
my_control.do_stuff_with_contiguous_memory(my_vec);

C ++

void MyControl::do_stuff_with_contiguous_memory(RuntimeComponent1::MyVector const& in_data)
{
    // Yay data is contiguous
    auto contiguous_data = in_data.as<MyVector>()->get_container().data();
}

Конечным результатом является то, что я могу передавать данные из C # в C ++ / WinRT, и эти данные будут смежными в C ++, что решает мою первоначальную проблему. Это работает, но мне интересно, может ли быть более простой / лучший способ?

...