当前位置: 代码迷 >> C# >> C++ 数据类型在C# 中转换的有关问题,尝试读取或写入受保护的内存。这通常指示其他内存已损坏
  详细解决方案

C++ 数据类型在C# 中转换的有关问题,尝试读取或写入受保护的内存。这通常指示其他内存已损坏

热度:91   发布时间:2016-05-05 04:02:15.0
C++ 数据类型在C# 中转换的问题,尝试读取或写入受保护的内存。这通常指示其他内存已损坏
小弟目前在用C#做一个调用C++开发的DLL的功能模块。其中数据类型转换的问题不是太懂。在这里请教一下各位大侠。

运行一直报错:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
初步估计是类型转换的问题。这里主要请教一下在C#中定义下面类型的数据是不是有问题?主要是结构体中的数据类型和枚举的使用。

先贴一下代码吧。
C++代码:实现登录的功能。  

/** 注册平台.
 @param   IN nPDLLHandle SDK句柄
 @param   IN pLoginInfo 用户登录信息
 @param   IN nTimeout 超时时长,单位毫秒
 @return  函数返回错误类型,参考dpsdk_retval_e
 @remark   int32_t 定义为 int
*/
DPSDK_DLL_API int32_t DPSDK_CALL_METHOD DPSDK_Login( IN int32_t nPDLLHandle, 
 IN Login_Info_t* pLoginInfo, 
 IN int32_t nTimeout = DPSDK_CORE_DEFAULT_TIMEOUT );
/** nPDLLHandle 在初始化得到值为1 **/

/** 其中Login_Info 的结构如下 **/
// 登录信息
typedef struct tagLoginInfo
{
    char szIp[DPSDK_CORE_IP_LEN]; // 服务IP,或者是域名DPSDK_CORE_IP_LEN为48
uint32_t nPort; // 服务端口
    char szUsername[DPSDK_CORE_USER_NAME_LEN]; // 用户名DPSDK_CORE_USER_NAME_LEN为64
char szPassword[DPSDK_CORE_PASSWORD_LEN]; // 密码DPSDK_CORE_PASSWORD_LEN为64
dpsdk_protocol_version_e nProtocol; // 协议类型
uint32_t iType; // 登陆类型,1为PC客户端, 2为手机客户端
}Login_Info_t;

/** 枚举 dpsdk_protocol_version_e 代码如下 **/
// 协议版本
typedef enum
{
DPSDK_PROTOCOL_VERSION_I = 1, // 一代协议
DPSDK_PROTOCOL_VERSION_II = 2, // 二代协议
}dpsdk_protocol_version_e;


// C#代码如下


        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="m_nDLLHandle">SDK句柄</param>
        /// <param name="stuLoginInfo">用户登录信息</param>
        /// <param name="timeout">无响应超时时间</param>
        /// <returns>登录状态</returns>
        [DllImport("C:\\DLLSDK\\DPSDK_Core.dll", CharSet = CharSet.Auto, SetLastError = true)]//, CallingConvention = CallingConvention.Cdecl  , CallingConvention = CallingConvention.StdCall
        public static extern int DPSDK_Login(int m_nDLLHandle, Login_Info_t stuLoginInfo, int timeout = 10000);

//定义 Login_Info_t 结构体如下:
    /// <summary>
    /// 用户登录信息
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct Login_Info_t
    {
        /// <summary>
        /// IP
        /// </summary>
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
        public char[] szIp;
        /// <summary>
        /// 端口
        /// </summary>
        public uint nPort;
        /// <summary>
        /// 登录用户名
        /// </summary>
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public char[] szUsername;
        /// <summary>
        /// 登录密码
        /// </summary>
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public char[] szPassword;
        /// <summary>
        /// 协议类型
        /// </summary>
        public dpsdk_protocol_version_e nProtocol;
        /// <summary>
        /// 登陆类型,1为PC客户端, 2为手机客户端
        /// </summary>
        public uint iType;
    }

//定义枚举如下:
    /// <summary>
    /// 协议类型
    /// </summary>
    public enum dpsdk_protocol_version_e
    {
        /// <summary>
        /// 一代协议
        /// </summary>
        DPSDK_PROTOCOL_VERSION_I = 1, // 一代协议
        /// <summary>
        /// 二代协议
        /// </summary>
        DPSDK_PROTOCOL_VERSION_II = 2, // 二代协议
    }


//实现登录方法如下:

        /// <summary>
        /// 登录平台
        /// </summary>
        /// <param name="strIp">平台IP</param>
        /// <param name="strUserName">用户名</param>
        /// <param name="strPassword">密码</param>
        /// <param name="strPort">端口号</param>
        /// <param name="nProtocol">协议类型</param>
        /// <param name="iType">登录类型</param>
        /// <returns></returns>
        public int DLLSDK_Login(string strIp, string strUserName, string strPassword, uint strPort, dpsdk_protocol_version_e nProtocol = dpsdk_protocol_version_e.DPSDK_PROTOCOL_VERSION_II, uint iType = 1)
        {
            //用户登录信息
            Login_Info_t login_info = new Login_Info_t();
            login_info.szIp = StringToCharArray(strIp,48);
            login_info.szUsername = StringToCharArray(strUserName, 64);
            login_info.szPassword = StringToCharArray(strPassword, 64);
            login_info.nPort = strPort;
            login_info.nProtocol = nProtocol;
            login_info.iType = iType;
            //登录  m_Dll_Hanlde 为全局变量 已经赋值为1
            int result = DPSDK_Login(m_Dll_Hanlde, login_info, 5000);
            return result;
        }

       /// <summary>
        /// 字符串转换成指定长度的字符数组
        /// </summary>
        /// <param name="str"></param>
        /// <param name="ToLength"></param>
        /// <returns></returns>
        public char[] StringToCharArray(string str, int ToLength)
        {
            char[] newArray = new char[ToLength];
            if (str != null)
            {
                if (str.Length > ToLength)
                {
                    str = str.Substring(0, ToLength - 1);
                }
                char[] oldArray = str.ToCharArray();
                //byte[] buffer = Encoding.ASCII.GetBytes(str);
                //string s = Encoding.ASCII.GetString(buffer);
                //oldArray = s.ToCharArray();
                int i = 0;
                foreach (char item in oldArray)
                {
                    newArray[i] = item;
                    i++;
                }
            }
            return newArray;
        }


------解决思路----------------------
stuLoginInfo
这个参数类型应该用IntPtr
通过Mashal.StructureToPtr把你的结构转换了再传进去
  相关解决方案