C++ clr заполнить Dictionary в нативной части кода

131
24 октября 2019, 08:30

Есть желание заполнять Dictionary вида Dictionary<Enum,Struct> в нативной части кода, используя возможности трансляции через vcclr.h. Толком ничего не получается, студия ругается почти на каждую строчку. Есть ли доступный пример использования? буду признателен.

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

Answer 1

Результатом поиска решений в этой области привели к нескольким направлениям:

  1. Использовать #include <cliext/adapter>, это ms решение по сути работает только внутри C++ функции (unmanaged). Экспортировать в C++clr (managed) код, то есть вернуть результатом работы функции не удастся, для этих целей не подходит.

  2. Интересное, хоть и не очень свежее решение marshalfx, но требует добавления описания собственных не generic объектов. С generic'ами работает отлично.

  3. Использование нативных прокси классов и директивы gcroot (vcclr.h). Именно на нем я остановился, по порядку:

Например все это проживает в нэймспейс:

  namespace MyNameSpace
  {

Имеем managed класс:

public ref class MyData
{
public:
   properties MyNameSpace::MyEnum MEnum;
   properties Int32 MyInt;
   properties Sting ^ MyStr;
}

Пишем для него прокси класс для unmanaged C++ кода:

class ProxyMyData
{
public:
    ProxyMyData()
    {
        vHandle = gcnew MyNameSpace::MyData();
    }
    gcroot<MyNameSpace::MyData^> vHandle;
    void Set(MyNameSpace::MyEnum id, Int32 idx, wchar_t *wstr)
    {
        vHandle->MEnum = id;
        vHandle->MyInt = idx;
        vHandle->MyStr = gcnew String(wstr);
    }
}

Определяем сокращение для Dictionary, чтобы было меньше букв :)

  namespace SCG = System::Collections::Generic;

Пишем прокси класс для Dictionary (unmanaged C++ код):

class ProxyDictionary
{
public:
    ProxyDictionary()
    {
        vHandle = gcnew SCG::Dictionary<MyNameSpace::MyEnum, MyNameSpace::MyData^>();
    }
    gcroot<SCG::Dictionary<MyNameSpace::MyEnum, MyNameSpace::MyData^>^> vHandle;
    void Add(MyNameSpace::MyEnum id, gcroot<MyNameSpace::MyData^> val)
    {
        vHandle->Add(id, val);
    }
};

Как это использовать в C++ unmanaged коде:

SCG::Dictionary<MyNameSpace::MyEnum, MyNameSpace::MyData^> ^ MyClass::MyFunc(Int32 idx, wchar_t *wstr)
{
    auto pdict = std::make_unique<ProxyDictionary>();
    auto pdata = std::make_unique<ProxyMyData>();
    pdata.get()->Set(
         MyNameSpace::MyEnum::TAG_1,
         idx,
         wstr
    );
    pdict.get()->Add(
         MyNameSpace::MyEnum::TAG_0,
         pdata.get()->vHandle
    );
    return pdict.get()->vHandle;
}

Для удобства создания прокси классов так-же можно написать простенький темплейт:

    template<class T>
    class ProxyObject
    {
    public:
        gcroot<T^> vHandle;
        ProxyObject() : vHandle(gcnew T()) {}
    };
    class ProxyMyData : public ProxyObject<MyNameSpace::MyData>
    {
    public:
       Set(/* ... */) { /* ... */ }
    }

Надеюсь что сэкономил кому либо пару лишних часов, информации на эту тему не очень много, к сожалению.

READ ALSO
Native wifi setprofile and connecting c++

Native wifi setprofile and connecting c++

Мой профиль ( через команду netsh wlan show networks) имеет вот такую кофигурацию:

154
Тип собираемых библиотек по умолчанию

Тип собираемых библиотек по умолчанию

По умолчанию у меня собираются статические библиотеки (если явно не указываю SHARED при создании библиотеки или BUILD_SHARED_LIBS при запуске cmake), а как...

131
C++ и русские символы

C++ и русские символы

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

144
Проблема с передачей матрицы в функцию

Проблема с передачей матрицы в функцию

В интернет искал ответ на свой вопрос, но не один из способов не работал

101