|
小弟目前在用C#做一个调用C++开发的DLL的功能模块。其中数据类型转换的问题不是太懂。在这里请教一下各位大侠。 运行一直报错:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。” 先贴一下代码吧。 /** 注册平台. @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;
}
|
|
|
自己先顶一下
|
|
| 60分 |
stuLoginInfo
这个参数类型应该用IntPtr 通过Mashal.StructureToPtr把你的结构转换了再传进去 |
|
我对C++和C#的转换还是个小白,请问能说具体点吗或者能给我贴个示例代码吗? |
|
//用户登录信息 Login_Info_t login_info = new Login_Info_t(); login_info.szIp = StringToCharArray(strIp, 48);//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; int nSizeOfLogin = Marshal.SizeOf(login_info); IntPtr intPtr = Marshal.AllocHGlobal(nSizeOfLogin); //将数据从托管对象封送到非托管内存块,该内存块开始地址为intPtr Marshal.StructureToPtr(login_info, intPtr, true); //登录 int result = -1; try { result = DaHua_SDK_API.DPSDK_Login(m_Dll_Hanlde, intPtr, 5000); } catch { result = -2; } finally { Marshal.FreeHGlobal(intPtr); //free tha memory } return result; 我这样做了一下好像还是不行。。 |
|
|
可以了。。不过需要将 C++ Login_Info_t 结构体中的 char 类型 定义为C# 中的 byte[] 类型
/// <summary>
/// 字符串转换成指定长度的字符数组
/// </summary>
/// <param name="str"></param>
/// <param name="ToLength"></param>
/// <returns></returns>
public byte[] StringToByteArray(string str, int ToLength)
{
byte[] newArray = new byte[ToLength];
if (str != null)
{
if (str.Length > ToLength)
{
str = str.Substring(0, ToLength - 1);
}
byte[] buffer = Encoding.ASCII.GetBytes(str);
int i = 0;
foreach (byte item in buffer)
{
newArray[i] = item;
i++;
}
}
return newArray;
}
/// <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 = StringToByteArray(strIp, 48);//StringToCharArray(strIp, 48);
login_info.szUsername = StringToByteArray(strUserName, 64);
login_info.szPassword = StringToByteArray(strPassword, 64);
login_info.nPort = strPort;
login_info.nProtocol = nProtocol;
login_info.iType = iType;
int nSizeOfLogin = Marshal.SizeOf(login_info);
IntPtr intPtr = Marshal.AllocHGlobal(nSizeOfLogin);
//将数据从托管对象封送到非托管内存块,该内存块开始地址为intPtr
Marshal.StructureToPtr(login_info, intPtr, true);
//登录
int result = -1;
try
{
result =DPSDK_Login(m_Dll_Hanlde, intPtr, 5000);
}
catch
{ result = -2; }
finally
{
Marshal.FreeHGlobal(intPtr); //free tha memory
}
return result;
}
|
|