C++;非托管函数回调char到C#char
我有一张C表格。我从C++ DLL调用非托管函数。 我有一个名为C++;非托管函数回调char到C#char,c#,c++,callback,pinvoke,intptr,C#,C++,Callback,Pinvoke,Intptr,我有一张C表格。我从C++ DLL调用非托管函数。 我有一个名为FUNDownDevCBEx的回调函数,它返回变量int-nType,IntPtr-pData 因此,指向struct\u tagGPSMDVRInfo p=(\u tagGPSMDVRInfo)Marshal.PtrToStructure(pData,typeof(\u tagGPSMDVRInfo))我可以得到指针变量 但是,当我指向szIDNO时,我只得到字符串的最后一个字符,我不知道为什么 我希望szIDNO以增量方式显示名
FUNDownDevCBEx
的回调函数,它返回变量int-nType,IntPtr-pData
因此,指向struct\u tagGPSMDVRInfo p=(\u tagGPSMDVRInfo)Marshal.PtrToStructure(pData,typeof(\u tagGPSMDVRInfo))代码>我可以得到指针变量
但是,当我指向szIDNO
时,我只得到字符串的最后一个字符,我不知道为什么
我希望szIDNO
以增量方式显示名称,但我只得到最后一个字符
预期:
00091
00001
01211
01222
01504
我得到的是:
4
2
1
1
1
四,
void FUNDownDevCBEx(intnType,IntPtr pData,Form1 Form1)
是返回的回调循环szIDNO
如有任何建议,将不胜感激
C++类型定义:
typedef struct _tagGPSInfo
{
int nID;
char szIDNO[32];
char szName[32];
char szSIMCard[16];
union
{
GPSInfo_S gDVRInfo;
GPSMobileInfo_S gMobileInfo;
GPSDVSInfo_S DVSInfo;
};
}GPSInfo_S, *LPGPSInfo_S;
C++回调函数如下所示:
void (CALLBACK * FUNDownDevCBEx)(int nType, void* pData, void * pUsr)
我的C#转换代码:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagGPSInfo
{
[MarshalAs(UnmanagedType.I4)]
public int nID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string szIDNO;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string szName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string szSIMCard;
}
private void devlist_Click(object sender, EventArgs e)
{
try
{
IntPtr _lHandle = IntPtr.Zero;
NETClass.NETCLIENT_DEVOpenDevDownEx(ref _lHandle);
NETClass.NETCLIENT_DEVSetCharEx( _lHandle);
FUNDownDevCBEx _1callback = new FUNDownDevCBEx(FUNDownDevCBEx);
NETClass.NETCLIENT_DEVRegDevDownCBEx( _lHandle, this, _1callback);
NETClass.NETCLIENT_DEVStartDevDownEx(_lHandle, 0,0);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "List Exception");
return;
}
}
static void FUNDownDevCBEx(int nType, IntPtr pData, Form1 form1)
{
try
{
_tagGPSInfo p = (_tagGPSMDVRInfo)Marshal.PtrToStructure(pData, typeof(_tagGPSInfo));
int nID = p.nID;
string szIDNO = p.szIDNO;
switch (nType)
{
case 0:
form1.Invoke((MethodInvoker)(() => form1.memoBox.AppendText(" DATA =" + pData + " nID=" + nID + " szIDNO=" + szIDNO + Environment.NewLine)));
break;
case 1:
//MessageBox.Show("GPS_DEV_DOWN_GROUP" + Environment.NewLine + " DATA =" + pData + " nID=" + nID);
break;
case 2:
//MessageBox.Show("GPS_DEV_DOWN_FAILED" + Environment.NewLine + " DATA =" + pData );
break;
case 3:
//MessageBox.Show("GPS_DEV_DOWN_SUC" + Environment.NewLine + " DATA =" + pData);
break;
case 4:
//MessageBox.Show("GPS_DEV_DOWN_RELATION" + Environment.NewLine + " DATA =" + pData + " nID=" + nID);
break;
default:
//MessageBox.Show("DEFAULT");
break;
}
//MessageBox.Show("nType= " + nType + " pData= " + pData);
NETClass.NETCLIENT_DEVStopDevDownEx(IntPtr.Zero);
NETClass.NETCLIENT_DEVCloseDevDownEx(IntPtr.Zero);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "FUNDownDevCBEx Exception");
return;
}
}
我的C#NETClass:
namespace ConversionTest
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void FUNDownDevCBEx(int nType, IntPtr data, Form1 form1);
class NETClass
{
[DllImport("libnetclient.dll", CallingConvention = CallingConvention.StdCall,SetLastError = true)]
public static extern int NETCLIENT_DEVOpenDevDownEx(ref IntPtr lpHandle);
[DllImport("libnetclient.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int NETCLIENT_DEVRegDevDownCBEx( IntPtr lHandle, Form1 form1, FUNDownDevCBEx _callback);
[DllImport("libnetclient.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int NETCLIENT_DEVStartDevDownEx( IntPtr lHandle, int nMgrType, int nDevType);
[DllImport("libnetclient.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int NETCLIENT_DEVStopDevDownEx( IntPtr lHandle);
[DllImport("libnetclient.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int NETCLIENT_DEVCloseDevDownEx( IntPtr lHandle);
[DllImport("libnetclient.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int NETCLIENT_DEVSetCharEx( IntPtr lHandle, bool bUtf8 = true);
}
}
谢谢你的评论。解决办法是晚上好好休息,早上喝杯咖啡
由于[StructLayout(LayoutKind.Sequential)]
是连续的,因此结构中的每个变量都必须是连续的。由于我的原始结构非常长,我在szIDNO
之前遗漏了一个int
变量,这导致从字符串中指向“miss”“
4个字符的指针
这就是我对它的理解,请随意评论
[StructLayout(LayoutKind.Sequential)]
public struct _tagGPSMDVRInfo
{
//struct now in proper sequence
[MarshalAs(UnmanagedType.I4)]
public int nID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string szName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string szIDNO;// <--- Now in correct position....
[MarshalAs(UnmanagedType.I4)]
public int nJingDu;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)]
public string strReserve;
}
static void FUNDownDevCBEx(int nType, IntPtr pData, Form1 form1)
{
try
{
switch (nType)
{
case 0:
_tagGPSMDVRInfo p = new _tagGPSMDVRInfo(); // Create the managed struct
p = Marshal.PtrToStructure<_tagGPSMDVRInfo>(pData);//simplify
int nID = p.nID;
string szIDNO = p.szIDNO;
form1.Invoke((MethodInvoker)(() => form1.textBox4.AppendText(" DATA =" + pData + " nID=" + nID + " szIDNO=" + szIDNO + Environment.NewLine)));
;
break;
case 1:
//MessageBox.Show("GPS_DEV_DOWN_GROUP" + Environment.NewLine + " DATA =" + pData + " nID=" + nID);
break;
case 2:
//MessageBox.Show("GPS_DEV_DOWN_FAILED" + Environment.NewLine + " DATA =" + pData );
break;
case 3:
//MessageBox.Show("GPS_DEV_DOWN_SUC" + Environment.NewLine + " DATA =" + pData);
break;
case 4:
//MessageBox.Show("GPS_DEV_DOWN_RELATION" + Environment.NewLine + " DATA =" + pData + " nID=" + nID);
break;
default:
//MessageBox.Show("DEFAULT");
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "FUNDownDevCBEx Exception");
return;
}
}
[StructLayout(LayoutKind.Sequential)]
公共结构\u tagGPSMDVRInfo
{
//结构现在按正确的顺序
[Marshallas(非托管类型.I4)]
公共国际网络;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=32)]
公共字符串名称;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=32)]
公共字符串szIDNO;//form1.textBox4.AppendText(“DATA=“+pData+”nID=“+nID+”szIDNO=“+szIDNO+Environment.NewLine));
;
打破
案例1:
//MessageBox.Show(“GPS_DEV_DOWN_GROUP”+Environment.NewLine+“DATA=“+pData+”nID=“+nID”);
打破
案例2:
//MessageBox.Show(“GPS_DEV_DOWN_FAILED”+Environment.NewLine+“DATA=“+pData”);
打破
案例3:
//MessageBox.Show(“GPS\u DEV\u DOWN\u SUC”+Environment.NewLine+“DATA=“+pData”);
打破
案例4:
//MessageBox.Show(“GPS_DEV_DOWN_RELATION”+Environment.NewLine+“DATA=“+pData+”nID=“+nID”);
打破
违约:
//MessageBox.Show(“默认”);
打破
}
}
捕获(例外情况除外)
{
Show(例如ToString(),“FUNDownDevCBEx异常”);
返回;
}
}
问题可能出在我们这里没有看到的代码中。创建@NineBerry我添加了我的net类和button事件。如果你的应用程序是64位的,可能存在对齐问题,因此c#期望szIDNO
从偏移量8开始,而dll将其放在偏移量4。因此,对于5个字符的字符串,您只能得到最后一个字符。@AlexSkalozub可能是,但在我测试的其他帐户中,还有其他长度不同的较长字符串,结果相同。。我认为这是一个字节数组或其他东西,它一直覆盖到最后一个字节,有点令人沮丧。我在32位设置上运行它。@alex我不这么认为。我想我们还不清楚这里到底发生了什么。不,这个结构定义不可能是正确的。确实存在问题,但这不是正确的解决方案。缺少结构的字段会产生此处所示的问题,这是有道理的。但是答案中给出的代码毫无意义,因为与原始问题相比,结构的相关开头没有改变。此外,指定“Size=16”对结构没有意义,因为它要长得多。