У меня есть структура в заголовочном файле c++, которая выглядит так:
typedef struct sFrameOfData
{
int iFrame;
float fDelay;
int nBodies;
sBodyData BodyData[MAX_N_BODIES];
int nUnidentifiedMarkers;
tMarkerData* UnidentifiedMarkers;
sAnalogData AnalogData;
sRecordingStatus RecordingStatus;
}
где sAnalogData
, tMarkerData
и sRecordingStatus
является пользовательским c++ Структура. Вызывается метод С#:
[DllImport("Cortex_SDK.dll")]
public static extern unsafe sFrameOfData* Cortex_GetCurrentFrame();
и я переписал структуры следующим образом:
[StructLayout(LayoutKind.Sequential)]
public unsafe struct sFrameOfData
{
private readonly int iFrame; //!< Cortex frame number
private readonly float fDelay; //!< Total time (seconds) from Camera to the Host sending the data
private readonly int nBodies; //!< The bodies should match the descriptions
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] private readonly sBodyData BodyData;
//!< The data for each body
private readonly int nUnidentifiedMarkers; //!< Number of unrecognized markers
private readonly tMarkerData* UnidentifiedMarkers; //!< The unrecognized markers
private readonly sAnalogData AnalogData; //!< The analog data packaged
private readonly sRecordingStatus RecordingStatus; //!< Info about name and frames being recorded
}
но я не cannot marshal 'return value'. Pointers cannot reference marshaled structures.
cannot marshal 'return value'. Pointers cannot reference marshaled structures.
Вероятно, вы можете начать со следующего скелета.
Создайте управляемый класс для хранения данных:
public class FrameOfData
{
public int iFrame { get; set; }
//...
}
Отметьте возвращаемое значение импорта p/invoke с помощью маршалов, указывающих класс, который будет выполнять пользовательский маршал (например, класс FrameMarshaler):
[DllImport("Cortex_SDK.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(FrameMarshaler))]
public static extern FrameOfData Cortex_GetCurrentFrame();
Класс FrameMarshaler отвечает за выполнение настраиваемого маршалинга, получая указатель на неуправляемую структуру и возвращающий управляемый объект, это можно сделать в методе MarshalNativeToManaged:
public class FrameMarshaler : ICustomMarshaler
{
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
}
public int GetNativeDataSize()
{
return -1;
}
public IntPtr MarshalManagedToNative(object ManagedObj)
{
throw new NotImplementedException();
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
// Here, we call C++/CLI code
FrameOfData frame = Marshaler.MarshalFrame(pNativeData);
return frame;
}
}
Метод Marshaler.MarshalFrame будет на сборке C++/CLI. Следующий код является примером маршалера C++/CLI для структуры:
#include "Cortex_SDK.h"
#pragma once
using namespace System;
public ref class Marshaler
{
public:
static FrameOfData^ MarshalFrame(IntPtr dispo)
{
// Cast the IntPtr to the unmanaged pointer
sFrameOfData* unmanaged = static_cast<sFrameOfData*>(dispo.ToPointer());
// Transform unmnaged pointer to a managed object
FrameOfData^ managed = gcnew FrameOfData();
managed->iFrame = unmanaged.iFrame;
// ...
}
}
[UnmanagedFunctionPointer(CallingConvenction.Cdecl)]
? Вам, вероятно, потребуется написать маршалер в C ++ / CLI, чтобы сопоставить указатель неуправляемого класса с управляемым объектом