Я пишу библиотеку оболочки на c # для c ++, используя файл заголовка dll, но не могу понять, как конвертировать типы.

0

У меня есть структура в заголовочном файле 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.

  • 0
    Можете ли вы показать свой код pinvoke? Вы пытались с [UnmanagedFunctionPointer(CallingConvenction.Cdecl)] ? Вам, вероятно, потребуется написать маршалер в C ++ / CLI, чтобы сопоставить указатель неуправляемого класса с управляемым объектом
  • 0
    Эй, код пинвока: CortexDll.sFrameOfData * a = CortexDll.Cortex_GetCurrentFrame ();
Показать ещё 5 комментариев
Теги:
interop

1 ответ

1

Вероятно, вы можете начать со следующего скелета.

Создайте управляемый класс для хранения данных:

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;
            // ...
        }
}
  • 0
    Это выглядит очень полезным, я собираюсь начать работать над этим сейчас. Я дам вам знать, если это работает.
  • 0
    Я предполагаю слишком много вещей из-за моего невежества в Cortex SDK, надеюсь, это поможет
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню