param.lpBuffer的结构体是:[StructLayout(LayoutKind.Sequential)] public struct GlyParam { public int handle; public int dwErrorCode; public int dwMessageID; public int dwRequestID; public int ulSize; public IntPtr lpBuffer; public string szParamName; }而param的值是通过回调函数返回来的: private void FrmCallback(ref GlyParam returnParam) { param = returnParam;
} param.lpBuffer的值是个指针地址:113476728现在就是要把param.lpBuffer转换成GlyDepositCounter结构.GlyDepositCounter glyDepositCounter = (GlyDepositCounter)Marshal.PtrToStructure(param.lpBuffer, typeof(GlyDepositCounter)); 这个时候出错:Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
dll和主程序的指针不能直接共享的,感觉会有问题,没这么用过。
[MarshalAs(UnmanagedType.LPWStr)]//根据c++中的类型设置成一样的 public string szParamName;
1、GlyDepositCounter里面的定义又套了结构,而且还套了几层,这样会导致Marshal在分配大小时,无法计算。你可以用Marsh.sizeof(typeof(GlyDepositCounter))来测试看看。因为无法分配大小,自然就读写不进去了。 2、可以考虑将需要套结构的地方转换成类来做,然后进行封装。到最终没有套结构的地方,再使用字节转换成结构。这样才比较保险。 public class ObjectSp { #region bytesToStruct /// <summary> /// Byte array to struct or classs. /// </summary> /// <param name="bytes">Byte array</param> /// <param name="type">Struct type or class type. /// Egg:class Human{...}; /// Human human=new Human(); /// Type type=human.GetType();</param> /// <param name="startIndex">Byte array start index.</param> /// <returns>Destination struct or class.</returns> public static object bytesToStruct(byte[] bytes, Type type, int startIndex = 0) { int size = Marshal.SizeOf(type);//Get size of the struct or class. if (bytes.Length < size) { return null; } IntPtr structPtr = Marshal.AllocHGlobal(size);//Allocate memory space of the struct or class. Marshal.Copy(bytes, startIndex, structPtr, size);//Copy byte array to the memory space. object obj = Marshal.PtrToStructure(structPtr, type);//Convert memory space to destination struct or class. Marshal.FreeHGlobal(structPtr);//Release memory space. return obj; } #endregion } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public class GlyDepositCounter { public uint EventNumber; public Tm Time; public uint dwSquentialNo; public uint dwUserID; public GlyCounters DepositData; public GlyDepositCounter(byte[] buff) { int offset = 0; EventNumber = BitConverter.ToUInt32(buff, 0); offset += sizeof(uint); Time = (Tm)ObjectSp.bytesToStruct(buff, typeof(Tm), offset); offset += Marshal.SizeOf(typeof(Tm)); dwSquentialNo = BitConverter.ToUInt32(buff, offset); offset += sizeof(uint); dwUserID = BitConverter.ToUInt32(buff, offset); offset += sizeof(uint); DepositData = analyDepositData(buff, offset); } private GlyCounters analyDepositData(byte[] buff, int offset) { GlyCounters DepositData = null; //仿照GlyDepositCounter进一步分析DepositData return DepositData; } } 3、建议增加CharSet和Pack参数,这样才能保证字节的对齐。比如[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=1)]
发消息拷贝数据用WM_COPYDATA。
param.lpBuffer的结构体是:[StructLayout(LayoutKind.Sequential)]
public struct GlyParam
{
public int handle;
public int dwErrorCode;
public int dwMessageID;
public int dwRequestID;
public int ulSize;
public IntPtr lpBuffer;
public string szParamName;
}而param的值是通过回调函数返回来的:
private void FrmCallback(ref GlyParam returnParam)
{
param = returnParam;
}
param.lpBuffer的值是个指针地址:113476728现在就是要把param.lpBuffer转换成GlyDepositCounter结构.GlyDepositCounter glyDepositCounter = (GlyDepositCounter)Marshal.PtrToStructure(param.lpBuffer, typeof(GlyDepositCounter));
这个时候出错:Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
public string szParamName;
2、可以考虑将需要套结构的地方转换成类来做,然后进行封装。到最终没有套结构的地方,再使用字节转换成结构。这样才比较保险。
public class ObjectSp
{ #region bytesToStruct
/// <summary>
/// Byte array to struct or classs.
/// </summary>
/// <param name="bytes">Byte array</param>
/// <param name="type">Struct type or class type.
/// Egg:class Human{...};
/// Human human=new Human();
/// Type type=human.GetType();</param>
/// <param name="startIndex">Byte array start index.</param>
/// <returns>Destination struct or class.</returns>
public static object bytesToStruct(byte[] bytes, Type type, int startIndex = 0)
{ int size = Marshal.SizeOf(type);//Get size of the struct or class.
if (bytes.Length < size)
{
return null;
}
IntPtr structPtr = Marshal.AllocHGlobal(size);//Allocate memory space of the struct or class.
Marshal.Copy(bytes, startIndex, structPtr, size);//Copy byte array to the memory space.
object obj = Marshal.PtrToStructure(structPtr, type);//Convert memory space to destination struct or class.
Marshal.FreeHGlobal(structPtr);//Release memory space.
return obj;
}
#endregion
} [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public class GlyDepositCounter
{
public uint EventNumber;
public Tm Time;
public uint dwSquentialNo;
public uint dwUserID;
public GlyCounters DepositData; public GlyDepositCounter(byte[] buff)
{
int offset = 0;
EventNumber = BitConverter.ToUInt32(buff, 0);
offset += sizeof(uint);
Time = (Tm)ObjectSp.bytesToStruct(buff, typeof(Tm), offset);
offset += Marshal.SizeOf(typeof(Tm));
dwSquentialNo = BitConverter.ToUInt32(buff, offset);
offset += sizeof(uint);
dwUserID = BitConverter.ToUInt32(buff, offset);
offset += sizeof(uint);
DepositData = analyDepositData(buff, offset);
} private GlyCounters analyDepositData(byte[] buff, int offset)
{
GlyCounters DepositData = null;
//仿照GlyDepositCounter进一步分析DepositData
return DepositData;
}
}
3、建议增加CharSet和Pack参数,这样才能保证字节的对齐。比如[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=1)]