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.