C++ 数据类型在C# 中转换的有关问题,尝试读取或写入受保护的内存。这通常指示其他内存已损坏
C++ 数据类型在C# 中转换的问题,尝试读取或写入受保护的内存。这通常指示其他内存已损坏
小弟目前在用C#做一个调用C++开发的DLL的功能模块。其中数据类型转换的问题不是太懂。在这里请教一下各位大侠。
运行一直报错:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
初步估计是类型转换的问题。这里主要请教一下在C#中定义下面类型的数据是不是有问题?主要是结构体中的数据类型和枚举的使用。
先贴一下代码吧。
C++代码:实现登录的功能。
// C#代码如下
------解决思路----------------------
stuLoginInfo
这个参数类型应该用IntPtr
通过Mashal.StructureToPtr把你的结构转换了再传进去
小弟目前在用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把你的结构转换了再传进去