Полагаю, это будет просто для гуру C ++ / CLI.
Я создаю оболочку, которая будет предоставлять высокопроизводительные собственные классы C ++ для приложения C # WinForms.Все прошло хорошо с простыми известными объектами, и я мог также обернуть функцию обратного вызова для делегирования.Но теперь я немного запутался.
У нативного класса C ++ есть следующий метод:
int GetProperty(int propId, void* propInOut)
Сначала я подумал, что могу использовать void * в качестве IntPtr, но потом я обнаружил, чтоМне нужно получить доступ к нему из C #.Поэтому я подумал о методе-обёртке:
int GetProperty(int propId, Object^ propInOut)
, но, просматривая исходный код C ++, я обнаружил, что метод должен модифицировать объекты.Очевидно, мне нужно:
int GetProperty(int propId, Object^% propInOut)
Теперь я не могу передать объекты нативным методам, поэтому мне нужно знать, как их обрабатывать в оболочке.Поскольку вызывающая сторона всегда должна знать, какие данные он / она передает / получает, я объявил обертку:
int GetProperty(int propId, int dataType, Object^% propInOut)
Я думаю, я могу использовать ее для передачи ссылочных типов и типов значений, например,int вот так:
Object count = 100; // yeah, I know boxing is bad but this will not be real-time call anyway
myWrapper.GetProperty(Registry.PROP_SMTH, DATA_TYPE_INT, ref count);
Я только что добавил набор констант dataType для всех нужных мне типов данных:
DATA_TYPE_INT, DATA_TYPE_FLOAT, DATA_TYPE_STRING, DATA_TYPE_DESCRIPTOR, DATA_TYPE_BYTE_ARRAY
(DATA_TYPE_DESCRIPTOR - простая структура с двумя полями: int Idи описание wstring - этот тип также будет перенесен, поэтому я предполагаю, что маршалинг будет простым копированием данных назад и вперед; все нативные строки - Unicode).
Теперь вопрос - как реализовать метод-оберткудля всех этих 5 типов?Когда я могу просто привести Object ^% к чему-либо (int, float безопасен для этого?) И перейти к нативному методу, когда мне нужно использовать pin_ptr и когда мне нужно более сложное маршалинг для native и обратно?
int GetProperty(int propId, int dataType, Object^% propInOut)
{
if(dataType == DATA_TYPE_INT)
{
int* marshaledPropInOut = ???
int result = nativeObject->GetProperty(propId, (void*)marshaledPropInOut);
// need to do anything more?
return result;
}
else
if(dataType == DATA_TYPE_FLOAT)
{
float* marshaledPropInOut = ???
int result = nativeObject->GetProperty(propId, (void*)marshaledPropInOut);
// need to do anything more ?
return result;
}
else
if(dataType == DATA_TYPE_STRING)
{
// will pin_ptr be needed or it is enough with the tracking reference in the declaration?
// the pointers won't get stored anywhere in C++ later so I don't need AllocHGlobal
int result = nativeObject->GetProperty(propId, (void*)marshaledPropInOut);
// need to do anything more?
return result;
}
else
if(dataType == DATA_TYPE_BYTE_ARRAY)
{
// need to convert form managed byte[] to native char[] and back;
// user has already allocated byte[] so I can get the size of array somehow
return result;
}
else
if(dataType == DATA_TYPE_DESCRIPTOR)
{
// I guess I'll have to do a dumb copying between native and managed struct,
// the only problem is pinning of the string again before passing to the native
return result;
}
return -1;
}
PS Может быть, есть более элегантное решение для обертывания этого метода void * со многими возможными типами данных?