Wrapper для DOTNET на родной написано в C++ CLI BestWay для передачи strutures?

Тем не менее, я пишу оболочку в C++ CLI для нашего приложения, чтобы дать некоторым новым частям (написанным на C#) сохранение и легкий доступ к старым родным библиотекам. Поэтому мне нужно передать некоторые структуры из C# в C++. Эти структуры определены в C++ Cli (dotnet), а также в C++.

Пример:

\\C+++
typedef struct
{                                                           
INFO16   jahr   ;
INFO8    monat  ;
INFO8    tag    ;
INFO8    stunde ;
INFO8    minute ;
}
SDATUM;

\\c++ cli
[StructLayout(LayoutKind::Explicit)]
public value struct SDATUM
{
public:
  [FieldOffset(0)]
  UInt16 jahr;
  [FieldOffset(2)]
  Byte monat;
  [FieldOffset(3)]
  Byte tag;
  [FieldOffset(4)]
  Byte stunde;
  [FieldOffset(5)]
  Byte minute;
};

Теперь я предоставляю некоторые функции в C++ cli, которые принимают этот тип как SDATUM типа dotnet в форме передачи по значению, по ссылке (sdatum%) и указателю sdatum*, как там, где есть соответствующие нативные функции. Что мне нужно для преобразования / приведения этих структур?

3 ответа

Решение

Я нашел другое решение, которое очень просто, коротко и не требует копирования данных. Вы можете вызывать нативные функции, которые хотят SDATUM C, следующим образом:

//signature
void someFunction(SDATUM datum);

void someFunctionWrapper(SDATUM datum){
pin_ptr<SDATUM>  datum_pin=&datum;


//::SDATUM refers to the C-Type
someFunction(*(::SDATUM*)datum_pin);
}

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

Я бы не стал заниматься кастингом. Скорее напишите класс ref, который содержит SDATUM. Предоставьте методы и свойства, которые устанавливают базовый SDATUM. Со стороны C# работайте с этим классом ref (или, что еще лучше, создайте интерфейс, который реализует этот класс, и сделайте так, чтобы сторона C# работала с этим интерфейсом). В C++/CLI вы можете получить доступ к собственной версии класса и при необходимости передать ее нативным методам.

Помните, что семантика копирования в C++ и.NET принципиально отличается: .NET использует общие ссылки для сбора мусора, а C++ использует конструкторы копирования.

C++ / CLI не позволит вам использовать нативные объекты в качестве членов управляемых классов, вам придется использовать указатели. Поэтому я буду использовать общие указатели boost для имитации семантики.NET.

Это может быть абстрагировано далеко. Вот класс, который я использую для представления классов C++ в мире.NET:

template <typename T>
ref class Handle
{
    boost::shared_ptr<T>* t;

    !Handle() 
    {
        if (t != nullptr)
        {
            delete t;
            t = nullptr;
        }
    }

    ~Handle() { this->!Handle(); }

public:
    Handle() : t(new boost::shared_ptr<T>((T*)0)) {}

    Handle(T* ptr) : t(new boost::shared_ptr<T>(ptr)) {}

    Handle% operator=(T* p)
    {
        if (p != t->get()) t->reset(p);
        return *this;
    }

    T* get() { return t->get(); }

    // Remember that operators are static in .NET
    static boost::shared_ptr<T> operator->(Handle% h) { return *h.t; }

    T& reference() { return *t->get(); }
    T const& const_reference() { return *t->get(); }
};

Тогда вы можете использовать:

ref class MyStruct
{
public:
    // Expose your .NET interface here, make it use the handle variable.

internal:
    Handle<Native::MyStruct> handle;
};

и использовать handle переменная-член в вашем C++ коде без ограничений. Это не будет показано в.NET. Затем вы можете выставлять свойства, методы доступа, операторы и т. Д. В стиле.NET.

Другие вопросы по тегам