C#中的Marshall C++结构

Marshall C++ structure in C#

本文关键字:结构 C++ Marshall 中的      更新时间:2023-10-16

我在这里提到了类似的问题,但没有得到问题的解决方案。

编组问题。我尝试了C++结构到C#,但做不到。我在pinvoke.net中搜索了任何解决方案的技巧,但找不到任何东西。请帮帮我!

错误消息

 An unhandled exception of type 'System.AccessViolationException' occurred in Unknown Module.
 Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

C++结构

    typedef struct SDK_ALARM_INFO
    {
        int nChannel;
        int iEvent;
        int iStatus;
        SDK_SYSTEM_TIME SysTime;
    }SDK_AlarmInfo;
     typedef struct SDK_SYSTEM_TIME{
         int  year;
         int  month;
         int  day;
         int  wday;
         int  hour;
         int  minute;
         int  second;
         int  isdst;
     }SDK_SYSTEM_TIME;

转换的结构C#

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SDK_ALARM_INFO
{
    public int nChannel;
    public int iEvent;
    public int iStatus;
    [MarshalAs(UnmanagedType.Struct)]
    public SDK_SYSTEM_TIME SysTime;
};
public struct SDK_SYSTEM_TIME
{
    public int year;   
    public int month;
    public int day;
    public int wday;
    public int hour;
    public int minute;
    public int second;
    public int isdst;
}

将指针编组到结构时出错。

C#代码

    private XMSDK.fMessCallBack msgcallback;
    bool MessCallBack(int lLoginID, string pBuf,uint dwBufLen, IntPtr dwUser)
    {
        SDK_ALARM_INFO ai = new SDK_ALARM_INFO();
        //getting error bottom line
        ai = (SDK_ALARM_INFO) Marshal.PtrToStructure(dwUser, typeof(SDK_ALARM_INFO)); // getting error this line           
        MessageBox.Show("Event: " + ai.iEvent.ToString() + " - Channel: " + ai.nChannel + " - GTime : " + ai.SysTime);
        return form.DealwithAlarm(lLoginID,pBuf,dwBufLen);
    }
    public int InitSDK()
    {
        //...
        msgcallback  = new XMSDK.fMessCallBack(MessCallBack);
        XMSDK.H264_DVR_SetDVRMessCallBack(msgcallback, this.Handle);
        //...
    }

MessCallBack函数C#

    class XMSDK {
       // ...
       public delegate bool fMessCallBack(int lLoginID, string pBuf, uint dwBufLen, IntPtr dwUser);
       [DllImport("NetSdk.dll")]
       public static extern void H264_DVR_SetDVRMessCallBack(fMessCallBack cbAlarmcallback, IntPtr lUser);
       //...
    }

我认为,结构转换错误和可能导致的错误。正在等待帮助。谢谢

结构声明看起来不错,但请确保您正确理解该SDK。在pBuf参数中而不是在dwUser中返回SDK_ALARM_INFO的可能性很高。通常,当某些SDK允许您使用用户定义的指针注册回调时,该指针会传递给回调方法(本例中为dwUser),所以我认为在您的情况下,dwUser实际上等于this.Handle

尝试将回调和方法声明更改为

delegate  bool fMessCallBack(int lLoginID, IntPtr pBuf, uint dwBufLen, IntPtr dwUser);
bool MessCallBack(int lLoginID, IntPtr pBuf, uint dwBufLen, IntPtr dwUser);

并呼叫

ai = (SDK_ALARM_INFO) Marshal.PtrToStructure(pBuf, typeof(SDK_ALARM_INFO));

也许这会有所帮助。