结构体传值时神奇的乱码问题,求指点 与dll之间通过结构体来设置设备的参数,使用设备官方程序来写入和读取参数没有任何问题,我通过调用dll来读取也没有问题,可是通过dll来写入参数后,再读取发现全是乱码。为了查看是否我写入时编码错误,表现为乱码,我将读取正确参数时的结构体和我用同样参数写入的结构体都转化为byte[] 然后保存到文件,通过winhex查看,两个文件的编码完全一样。为什么会出现这种情况呢? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我的读参数和写参数的代码如下: public override int GetFTP(IntPtr hDev, ref string URL, ref string UserName, ref string Passwd, ref uint Port) { DVSNETClient.DVSNET_FTP_PARAM dfp = new DVSNETClient.DVSNET_FTP_PARAM(); IntPtr pdfp = Marshal.AllocHGlobal(Marshal.SizeOf(dfp)); uint len = (uint)Marshal.SizeOf(new DVSNETClient.DVSNET_FTP_PARAM()); int r = GetServerParam(hDev, (uint)(0x10000 + 162), 0, pdfp, len); dfp = (DVSNETClient.DVSNET_FTP_PARAM)Marshal.PtrToStructure(pdfp, typeof(DVSNETClient.DVSNET_FTP_PARAM)); URL = new string(dfp.sServerIp); UserName = new string(dfp.sUserName); Passwd = new string(dfp.sPasswd); Port = dfp.nServerPort; //File.WriteAllBytes("1.txt", StructToBytes(dfp)); return r; } public override int SetFTP(IntPtr hDev, string URL, string UserName, string Passwd, uint Port) { DVSNETClient.DVSNET_FTP_PARAM dfp = new DVSNETClient.DVSNET_FTP_PARAM(); dfp.nServerPort = Port; dfp.sServerIp = GetCharFromString(URL,48); dfp.sUserName = GetCharFromString(UserName,16); dfp.sPasswd = GetCharFromString(Passwd,16); IntPtr pdfp = Marshal.AllocHGlobal(Marshal.SizeOf(dfp)); uint len = (uint)Marshal.SizeOf(new DVSNETClient.DVSNET_FTP_PARAM()); //File.WriteAllBytes("2.txt", StructToBytes(dfp)); int r = SetServerParam(hDev, (uint)(0x10000 + 161), 0, pdfp, len); return r; } char[] GetCharFromString(string str,int len) { char[] c = new char[len]; byte[] ascii = Encoding.ASCII.GetBytes(str.PadRight(len,'\0')); c = Encoding.ASCII.GetChars(ascii); return c; 在官方demo中C++代码如下:void CDVSSetNetFtpDlg::RequestParams(){ if(NULL == m_hServer) return ; ZeroMemory(&m_FTPPara,sizeof(DVSNET_FTP_PARAM)); DVSNET_GetServerParam(m_hServer,GET_FTP_PARAM,0,&m_FTPPara,sizeof(DVSNET_FTP_PARAM)); m_sServURL = m_FTPPara.sServerIp; m_nServPort = m_FTPPara.nServerPort; m_sUserName = m_FTPPara.sUserName; m_sPasswd = m_FTPPara.sPasswd; UpdateData(FALSE);}void CDVSSetNetFtpDlg::OnBtnSetftp() { // TODO: Add your control notification handler code here if(NULL == m_hServer) return; UpdateData(TRUE); UnicodeToString(m_sServURL,m_FTPPara.sServerIp,48,0); m_FTPPara.nServerPort = m_nServPort; UnicodeToString(m_sUserName,m_FTPPara.sUserName , 16,LANGID_ZH_CN); UnicodeToString(m_sPasswd,m_FTPPara.sPasswd , 16,LANGID_ZH_CN); DVSNET_SetServerParam(m_hServer,SET_FTP_PARAM,0,&m_FTPPara,sizeof(DVSNET_FTP_PARAM)); CDVSSetupDlg *pSetupDlg = (CDVSSetupDlg *)GetParent()->GetParent()->GetParent()->GetParent(); pSetupDlg->SetModified();}void UnicodeToString(LPCTSTR szUnicode,char *szString,int nLen,DWORD nLanguageID,BOOL bAddNull){ strncpy(szString,szUnicode,nLen);} 我已经想不到办法了,我把接收的到数据一个一个byte的对比 , 感觉完全一样,但是同样的数据回写就不行。对了,我做过一个试验就是将收到的结构体马上回写,这样就OK。只要是经过我的控件给出的,虽然参数相同,但是发送过去后显示就是乱码 估计是你写入和读取时的Encoding不对,你可以指定一致,试试看 现在确定是ascii编码的,我在上面的代码里面有把字符串都转为ascii编码的char[] 可是还是不对 刚发现c#的char是16位的, 如何能把unicode的字符串转换为c++ 样子的char[] 呢? 使用IntPtr把 c++ char * 代表的是指针,IntPtr ptr = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi("demo");注意指向非托管内存,结构体中声明修改下把 发现一个更加诡异的问题,我从设备中读取数据,然后复制这数据再写入设备,再从设备中读出数据,原始数据是正确的,可是我读出的数据是乱码,我的代码如下: public override int GetFTP(IntPtr hDev, ref string URL, ref string UserName, ref string Passwd, ref uint Port) { //第一次读取数据 DVSNETClient.DVSNET_FTP_PARAM dfp = new DVSNETClient.DVSNET_FTP_PARAM(); IntPtr pdfp = Marshal.AllocHGlobal(Marshal.SizeOf(dfp)); uint len = (uint)Marshal.SizeOf(new DVSNETClient.DVSNET_FTP_PARAM()); int r = GetServerParam(hDev, (uint)(0x10000 + 162), 0, pdfp, len); dfp = (DVSNETClient.DVSNET_FTP_PARAM)Marshal.PtrToStructure(pdfp, typeof(DVSNETClient.DVSNET_FTP_PARAM)); URL = Encoding.ASCII.GetString(dfp.sServerIp); UserName = Encoding.ASCII.GetString(dfp.sUserName); Passwd = Encoding.ASCII.GetString(dfp.sPasswd); Port = dfp.nServerPort; //复制读出的数据 DVSNETClient.DVSNET_FTP_PARAM ddfp = new DVSNETClient.DVSNET_FTP_PARAM(); IntPtr pddfp = Marshal.AllocHGlobal(Marshal.SizeOf(ddfp)); ddfp.nServerPort = Port; ddfp.sServerIp = dfp.sServerIp; ddfp.sUserName = dfp.sUserName; ddfp.sPasswd = dfp.sPasswd; //将复制的数据重新写入 r = SetServerParam(hDev, (uint)(0x10000 + 161), 0, pddfp, len); //再次读出刚写入的数据,结果是乱码 r = GetServerParam(hDev, (uint)(0x10000 + 162), 0, pdfp, len); dfp = (DVSNETClient.DVSNET_FTP_PARAM)Marshal.PtrToStructure(pdfp, typeof(DVSNETClient.DVSNET_FTP_PARAM)); URL = Encoding.ASCII.GetString(dfp.sServerIp); UserName = Encoding.ASCII.GetString(dfp.sUserName); Passwd = Encoding.ASCII.GetString(dfp.sPasswd); Port = dfp.nServerPort; return r; } 结构中用的是char[] 定长的,我现在c#中用byte[] C# winform程序关于DataGridView刷新明白的入,多谢 [to->ALL] __ 问题bat的问题 __ windows service 什么时候用,有什么好处? c#SOCKET接收数据问题 在winform上用Graphics画一个圆,如何用鼠标移动到圆上,圆的颜色改变? 小弟remoting不熟 请教一个有关的问题. datetimepicker的bug? 关于静态属性调用的一个问题??????? c#程序为什么在.NET中运行不了? 请问老手们:有关OA的 C# 串口通讯问题,大家帮忙解决一下@@@ 请教一个关于反射的问题
{
DVSNETClient.DVSNET_FTP_PARAM dfp = new DVSNETClient.DVSNET_FTP_PARAM();
IntPtr pdfp = Marshal.AllocHGlobal(Marshal.SizeOf(dfp));
uint len = (uint)Marshal.SizeOf(new DVSNETClient.DVSNET_FTP_PARAM());
int r = GetServerParam(hDev, (uint)(0x10000 + 162), 0, pdfp, len);
dfp = (DVSNETClient.DVSNET_FTP_PARAM)Marshal.PtrToStructure(pdfp, typeof(DVSNETClient.DVSNET_FTP_PARAM));
URL = new string(dfp.sServerIp);
UserName = new string(dfp.sUserName);
Passwd = new string(dfp.sPasswd);
Port = dfp.nServerPort; //File.WriteAllBytes("1.txt", StructToBytes(dfp)); return r;
} public override int SetFTP(IntPtr hDev, string URL, string UserName, string Passwd, uint Port)
{
DVSNETClient.DVSNET_FTP_PARAM dfp = new DVSNETClient.DVSNET_FTP_PARAM();
dfp.nServerPort = Port;
dfp.sServerIp = GetCharFromString(URL,48);
dfp.sUserName = GetCharFromString(UserName,16);
dfp.sPasswd = GetCharFromString(Passwd,16);
IntPtr pdfp = Marshal.AllocHGlobal(Marshal.SizeOf(dfp));
uint len = (uint)Marshal.SizeOf(new DVSNETClient.DVSNET_FTP_PARAM()); //File.WriteAllBytes("2.txt", StructToBytes(dfp)); int r = SetServerParam(hDev, (uint)(0x10000 + 161), 0, pdfp, len);
return r;
} char[] GetCharFromString(string str,int len)
{
char[] c = new char[len];
byte[] ascii = Encoding.ASCII.GetBytes(str.PadRight(len,'\0'));
c = Encoding.ASCII.GetChars(ascii);
return c;
{
if(NULL == m_hServer)
return ;
ZeroMemory(&m_FTPPara,sizeof(DVSNET_FTP_PARAM));
DVSNET_GetServerParam(m_hServer,GET_FTP_PARAM,0,&m_FTPPara,sizeof(DVSNET_FTP_PARAM));
m_sServURL = m_FTPPara.sServerIp;
m_nServPort = m_FTPPara.nServerPort;
m_sUserName = m_FTPPara.sUserName;
m_sPasswd = m_FTPPara.sPasswd;
UpdateData(FALSE);
}void CDVSSetNetFtpDlg::OnBtnSetftp()
{
// TODO: Add your control notification handler code here
if(NULL == m_hServer)
return;
UpdateData(TRUE);
UnicodeToString(m_sServURL,m_FTPPara.sServerIp,48,0);
m_FTPPara.nServerPort = m_nServPort;
UnicodeToString(m_sUserName,m_FTPPara.sUserName , 16,LANGID_ZH_CN);
UnicodeToString(m_sPasswd,m_FTPPara.sPasswd , 16,LANGID_ZH_CN);
DVSNET_SetServerParam(m_hServer,SET_FTP_PARAM,0,&m_FTPPara,sizeof(DVSNET_FTP_PARAM));
CDVSSetupDlg *pSetupDlg = (CDVSSetupDlg *)GetParent()->GetParent()->GetParent()->GetParent();
pSetupDlg->SetModified();
}void UnicodeToString(LPCTSTR szUnicode,char *szString,int nLen,DWORD nLanguageID,BOOL bAddNull)
{
strncpy(szString,szUnicode,nLen);
}
我已经想不到办法了,我把接收的到数据一个一个byte的对比 , 感觉完全一样,但是同样的数据回写就不行。对了,我做过一个试验就是将收到的结构体马上回写,这样就OK。只要是经过我的控件给出的,虽然参数相同,但是发送过去后显示就是乱码
现在确定是ascii编码的,我在上面的代码里面有把字符串都转为ascii编码的char[] 可是还是不对
IntPtr ptr = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi("demo");
注意指向非托管内存,结构体中声明修改下把
{
//第一次读取数据
DVSNETClient.DVSNET_FTP_PARAM dfp = new DVSNETClient.DVSNET_FTP_PARAM();
IntPtr pdfp = Marshal.AllocHGlobal(Marshal.SizeOf(dfp));
uint len = (uint)Marshal.SizeOf(new DVSNETClient.DVSNET_FTP_PARAM());
int r = GetServerParam(hDev, (uint)(0x10000 + 162), 0, pdfp, len);
dfp = (DVSNETClient.DVSNET_FTP_PARAM)Marshal.PtrToStructure(pdfp, typeof(DVSNETClient.DVSNET_FTP_PARAM));
URL = Encoding.ASCII.GetString(dfp.sServerIp);
UserName = Encoding.ASCII.GetString(dfp.sUserName);
Passwd = Encoding.ASCII.GetString(dfp.sPasswd);
Port = dfp.nServerPort;
//复制读出的数据
DVSNETClient.DVSNET_FTP_PARAM ddfp = new DVSNETClient.DVSNET_FTP_PARAM();
IntPtr pddfp = Marshal.AllocHGlobal(Marshal.SizeOf(ddfp));
ddfp.nServerPort = Port;
ddfp.sServerIp = dfp.sServerIp;
ddfp.sUserName = dfp.sUserName;
ddfp.sPasswd = dfp.sPasswd;
//将复制的数据重新写入
r = SetServerParam(hDev, (uint)(0x10000 + 161), 0, pddfp, len);
//再次读出刚写入的数据,结果是乱码
r = GetServerParam(hDev, (uint)(0x10000 + 162), 0, pdfp, len);
dfp = (DVSNETClient.DVSNET_FTP_PARAM)Marshal.PtrToStructure(pdfp, typeof(DVSNETClient.DVSNET_FTP_PARAM));
URL = Encoding.ASCII.GetString(dfp.sServerIp);
UserName = Encoding.ASCII.GetString(dfp.sUserName);
Passwd = Encoding.ASCII.GetString(dfp.sPasswd);
Port = dfp.nServerPort;
return r;
}
结构中用的是char[] 定长的,我现在c#中用byte[]