千辛万苦,经过坛子里的高手指点,用unsafe的写法c#的代码终于能得到c++ dll里传过来的值了(尽管debug的时候还是会有错误,但好歹现在有数据了),现在有个问题dll里有参数是void*,根据类型转换成不同的结构,比如提供的c++客户端例子是这样写的:
RecvDataHandler(const TMsgHead *pAppHead, const void *pData){
switch(pMsgHead->sDataType)
{
case 1:{//pData转成单一结构TStuct1
TStuct1 *p1= (TStuct1 *)pData;
sprintf(p1.data);
....
}
case 2:{//pData转成结构数组TStuct2
THead *pHead = (THead *)pAppHead;
TStuct2 *p2 = (TStuct2 *)pData;
for(i = 0; i < pHead ->nItems; i++)
{
//
sprintf(p2[i].nStatus);
......
}
}}我c#这样写 unsafe void RecvDataHandler(ref TMsgHead pAppHead, IntPtr pData)
{
switch (pMsgHead.sDataType)
{
1:{
TStuct1 d1 = new TStuct1 ();
d1 = (TStuct1)Marshal.PtrToStructure(pData, typeof(TStuct1));
logger.Info(d1.data);//能正常得到data值
}
2:{
TStuct2 d = new TStuct2[pMsgHead.nItems];
//这句一直报错
d = (TStuct2[])Marshal.PtrToStructure(pData, typeof(TStuct2[]));
}
}
RecvDataHandler(const TMsgHead *pAppHead, const void *pData){
switch(pMsgHead->sDataType)
{
case 1:{//pData转成单一结构TStuct1
TStuct1 *p1= (TStuct1 *)pData;
sprintf(p1.data);
....
}
case 2:{//pData转成结构数组TStuct2
THead *pHead = (THead *)pAppHead;
TStuct2 *p2 = (TStuct2 *)pData;
for(i = 0; i < pHead ->nItems; i++)
{
//
sprintf(p2[i].nStatus);
......
}
}}我c#这样写 unsafe void RecvDataHandler(ref TMsgHead pAppHead, IntPtr pData)
{
switch (pMsgHead.sDataType)
{
1:{
TStuct1 d1 = new TStuct1 ();
d1 = (TStuct1)Marshal.PtrToStructure(pData, typeof(TStuct1));
logger.Info(d1.data);//能正常得到data值
}
2:{
TStuct2 d = new TStuct2[pMsgHead.nItems];
//这句一直报错
d = (TStuct2[])Marshal.PtrToStructure(pData, typeof(TStuct2[]));
}
}
重复创建?
现在运行到
d = (TStuct2[])Marshal.PtrToStructure(pData, typeof(TStuct2[]));
程序就异常中止了
for (int i = 0; i < pMsgHead.nItems; i++)
d[i] = (TStuct2) Marshal.PtrToStructure(pData + Marshal.SizeOf(typeof(TStuct2))*i, typeof(TStuct2));
int nStatus;
unsigned int nPre;
unsigned int nAsk[10];
__int64 iVolume;
char chfix[4]
}我定义成 [StructLayout(LayoutKind.Sequential)]
struct TStuct2{
[MarshalAs(UnmanagedType.I4)]
public int nStatus; [MarshalAs(UnmanagedType.I4)]
public unsigned int nPre; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32 * 4)]
public unsigned int[] nAsk[];
[MarshalAs(UnmanagedType.I8)]
public Int64 iVolume; [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] chfix
}2个问题:
1、定义__int64返回来的都是0,比如 iVolume字段,我改成long也是0,应该有其他值的
2、dll会很频繁调用这个回调函数写入数据(每秒都有上千笔),程序运行一段时间接收到一部分数据后又
报“该线程尝试读写某个虚拟地址,而它对该地址不具有相应的访问权限”,然后中止。。
internal struct TStuct2
{
[MarshalAs(UnmanagedType.I4)] public int nStatus;
[MarshalAs(UnmanagedType.U4)] public uint nPre;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10, ArraySubType = UnmanagedType.U4)] public uint[] nAsk;
[MarshalAs(UnmanagedType.I8)] public Int64 iVolume;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] chfix;
}
加上结构体大小,再转成 intptr 再获取下一个结构。