Как исправить 'Cannot marshal' возвращаемое значение ': неверная комбинация управляемого / неуправляемого типа (Int / UInt должен быть связан с SysInt или SysUInt).' - PullRequest
0 голосов
/ 23 октября 2019

Я пытаюсь вернуть структуру из обратного вызова C ++ из C #, и я получаю ошибку, как описано в заголовке.

Я ценю, что есть много информации, но я хотел бы включить слишком много, а не недостаточно.

Я пытался вернуть функцию в виде структуры, но затем прочитать ее может бытьпроще вернуть функцию в виде IntPtr и использовать Marshal.PtrtoStructure.

Функция, которую я хочу вызвать, происходит из .dll, которая поступает из другого источника, и ввод:

C ++:

rVDACQ_Connect(int, tVDACQ_CallBackProc, void*, short*, int)

функция в примере кода (C ++) возвращает структуру (rACQ_CallBackRec), которая выглядит следующим образом:

rACQ_CallBackRec = theApp.m_Intf.rVDACQ_Connect(cVDACQ_FBright, CALLBACK_Acquisition, this, m_FrmBuffer, 0);
//rACQ_CallBackRec is the struct type tVDACQ_CallBackRec (as described below)

С CALLBACK_Aquisition:

extern "C" {
    __declspec(dllexport) void _stdcall CALLBACK_Acquisition(tVDACQ_CallBackRec* AR)
    {
        tVDACQ_CallBackProc test;
        ((CPreviewDlg*)AR->rUserParam)->My_ACQ_CallBack(AR, test);
    }
}

Структура структуры следующая:

typedef struct {
    int    rFlags,            // combination of cVDACQ_Fxxxx
        rType,             // cVDACQ_ETxxx
        rEvent,            // cVDACQ_Exxx
        rSocket;           // 0:no relation to a 'socket'; otherwise socket's ID>0 (event's source ID) 
    TCHAR  rMsg[256];         // message (trace, wrn, err)
    int    rFrameWidth,       // full frame width
        rFrameHeight;      // full frame height
    short* rFrameBuffer;      // user supplied frame buffer "AFrameBuffer"
    union {
        int    rCaptureRows;      // # of received rows (for single frame acquisition)
        int    rCaptureFrames;    // # of received full frames (for framegrabber)
    };
    int    rCapturePercent;   // received data in percents
    void* rUserCallBackProc, // user supplied "ACallBackProc"
        * rUserParam;        // user supplied "AUserParam"
    int    rAborted;          // 1: VDACQ_Abort -1:internally
    void* rPacketData;       // pointer to received packet; usually it is nil  
    int    rFGControl;        // frame-grabber's control flags
} tVDACQ_CallBackRec;

typedef void(_stdcall* tVDACQ_CallBackProc)(tVDACQ_CallBackRec*); //The Callback

C #

Я создал процедуру обратного вызова в C #, а также структуру и PInvoke:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate void tVDACQ_CallBackProc(tVDACQ_CallBackRec AR);

[DllImport("C:\\Users\\jch\\source\\repos\\FlatPanelSensor\\x64\\Debug\\VADAV_AcqS.dll", EntryPoint = "CALLBACK_Acquisition", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern void CALLBACK_Acquisition(tVDACQ_CallBackRec AR);

[DllImport("C:\\Users\\jch\\source\\repos\\FlatPanelSensor\\FlatPanelSensor\\bin\\Debug\\VADAV_FGM_64.dll", EntryPoint = "VDACQ_Connect", CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.I4)]
        public unsafe static extern IntPtr VDACQ_Connect(int i, [MarshalAs(UnmanagedType.FunctionPtr)] tVDACQ_CallBackProc proc, dynamic n, IntPtr[] buffer, int j);

Структура:

[StructLayout(LayoutKind.Sequential)]
        public struct tVDACQ_CallBackRec
        {
            public int rFlags;
            public int rType;
            public int rEvent;
            public int rSocket;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string rMsg;            

            public int rFrameWidth;
            public int rFrameHeight;

            public IntPtr rFrameBuffer;

            public int rCaptureRows;
            public int rCaptureFrames;
            public int rCapturePercent;

            public IntPtr rUserCallBackProc;
            public IntPtr rUserParam;

            public int rAborted;

            public IntPtr rPacketData;

            public int rFGControl;
        }

CallBack:

tVDACQ_CallBackProc callBack =
                (AR) =>
                {
                    CALLBACK_Acquisition(AR); //Don't know how necessary this 
                                                is
                };

Вызов функции:

IntPtr work = VDACQ_Connect(0, callBack, this, m_FrmBuffer, 0);
//I know 'this' isn't defined as a void* in my DLLImport,
//but making it an IntPtr didn't work either so 
//the only type I could think of was dynamic.

Если бы я мог вернуть это как IntPtr или, что еще лучше, структура, которую я определил в своем коде C #, была бы великолепна.

Если вам нужно больше информацииТогда, пожалуйста, дайте мне знать, так как я думаю, что я включил все.

...