Я пытаюсь вернуть класс C# (не структуру!) Из функции C ++ (используя параметр out). Это сторона C#:
[StructLayout(LayoutKind.Sequential)]
public class OutClass
{
public int X;
}
// This interface function will be mapped to the C++ function
void MarshalOutClass(out OutClass outClass);
Часть C ++ выглядит так:
struct OutClass
{
int x = 0;
};
extern "C" MARSHAL_TESTS_API void MarshalOutClass(OutClass** out);
Отображение функций работает через специальный механизм и не является частью этого вопроса. Все атрибуты маршалинга обрабатываются нормально.
В C# мы обычно объявляем out аргументы встроенными, например:
MarshalOutClass(out var outClass);
DoSomething(outClass);
Поскольку ссылочные типы C# маршалируются по указателю, я решил, что я придется добавить еще один указатель на параметры ref
или out
. Поэтому я использую OutClass**
на стороне C ++.
Я предполагаю , что C# переводит
MarshalOutClass(out var outClass);
часть примерно в
OutClass outClass = default(OutClass);
MarshalOutClass(ref outClass);
, что является ссылкой на null
, или на стороне C ++: указатель на nullptr
. Это не будет проблемой для типов значений C# (также известных как struct
), потому что по умолчанию они сконструированы экземпляром по умолчанию.
Это означает, что мне придется вручную создать экземпляр моего объекта на стороне C ++ и упорядочить его обратно до C#.
void MarshalOutClass(OutClass** out)
{
auto ptr = static_cast<OutClass*>(CoTaskMemAlloc(sizeof(OutClass)));
*ptr = OutClass{};
*out = ptr;
}
Код вроде работает, но я не уверен, утекаю ли я с этим памятью, или если маршаллер собирается взять ухаживать за ним должным образом. Я не занимаюсь очисткой на стороне C#.
Это подводит меня к следующим вопросам:
- - это мое предположение о том, как
ref
и out
переведено на C ++ правильно? - здесь
CoTaskMemAlloc
правильная функция? - нужно ли мне выполнять какие-либо дополнительные задачи, связанные с управлением памятью (с обеих сторон)?
- есть общий подход правильный здесь? Что мне делать по-другому?
Я знаю, что static_cast<OutClass*>(CoTaskMemAlloc(sizeof(OutClass)))
здесь немного схематично, но предположим, что OutClass
всегда является тривиальным типом.