本帖最后由 Soja 于 2013-12-23 11:57:47 编辑

解决方案 »

  1.   

    无法读写受保护的内存,指针不对。param.lpBuffer  这个你那里来的?直接c++的指针发过来的么?
    发消息拷贝数据用WM_COPYDATA。
      

  2.   


    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.
      

  3.   

    dll和主程序的指针不能直接共享的,感觉会有问题,没这么用过。
      

  4.   

    [MarshalAs(UnmanagedType.LPWStr)]//根据c++中的类型设置成一样的
    public string szParamName;
      

  5.   

    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)]