首页 > 解决方案 > 如何修复“无法封送“返回值”:托管/非托管类型组合无效(Int/UInt 必须与 SysInt 或 SysUInt 配对)。

问题描述

我试图从 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;
        }

打回来:

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# 代码中定义的结构会很棒。

如果您需要更多信息,请告诉我,因为我认为我包括了所有内容。

标签: c#c++structpinvokedllimport

解决方案


推荐阅读