C# 中的 Marshall C++ 结构

Posted

技术标签:

【中文标题】C# 中的 Marshall C++ 结构【英文标题】:Marshall C++ structure in C# 【发布时间】:2014-09-21 15:26:43 【问题描述】:

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

编组问题。我尝试将 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);

       //...
    

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

【问题讨论】:

Please add the exact error messages to you question. 对不起,我更新了帖子。 【参考方案1】:

结构声明看起来不错,但请确保您正确理解该 SDK。 SDK_ALARM_INFO 很有可能在 pBuf 参数中返回,而不是在 dwUser 中。通常当某些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));

这可能会有所帮助。

【讨论】:

以上是关于C# 中的 Marshall C++ 结构的主要内容,如果未能解决你的问题,请参考以下文章

在 c# 中使用 ifdef 和联合的 Marshall 结构

C# - Marshall by value 问题!

C# 中的元帅 C++“char**”

创建可以从 c# 和 c++ 中使用的 c# dll

sql [存档Marshall中的陈旧瞬态]从Marshall Inbox归档旧对象#marshall

Marshall结构通过sendmessage将其传递给delphi记录