昨天的贴没人给了!今天再开个讨论讨论!解决的问题:复制数组在内存中的数据到自定义结构中。
类似功能:
  在C++中 
  原型:extern  void  *memcpy(void  *dest,  void  *src,  unsigned  int  count);  
  功能:由src所指内存区域复制count个字节到dest所指内存区域。 昨天有朋友回帖说在c#中Marshal.Copy可以实现类似功能。自己查了下帮助,觉得应该是可以的,但使用上有点小问题。
  原型:Marshal.Copy (Byte[], Int32, IntPtr, Int32) 
  功能:将一维的托管 8 位无符号整数数组中的数据复制到非托管内存指针。 //结构
struct retu 
        { 
            public byte a;//数据头 
            public byte b;//下位机地址 
            public byte c;//命令 
            public char d;//状态 
            public float e;//力 
            public float f;//电压 
            public float g;//电流 
            public float h;//运动时间 
            public byte i;//数据长度 
            public byte Verify;//校验 
            public byte j;//数据尾 
        } 
//数组 
Byte[] mbyte = new Byte[28]; //使用方法
Marshal.Copy(mbyte, 0, &ret, 28); 
异常,说我有些参数无效。应该是&ret的问题。这个参数需要的是IntPtr类型(要复制到的内存指针)。 
请问,怎么得出这个结构的指针?
强制类型转换肯定不行。那么这个方法怎么用到这个问题上呢?

解决方案 »

  1.   

    还有个数据结构叫GCHandle. GCHandle retPinned = GCHandle.Alloc(ret);
    try 
    {
      Marshal.Copy(mbyte, 0, AddrOfPinnedObject, 28);
    }
    finally
    {
      retPinned.Free();
    }
      

  2.   

    See one of your post. The answer was already there.
    c#中如何解决类似问题?使用指针可以么If you use Marshal.PtrToStructure(), then you don't need to Marshal.Copy().
    If you do want to Marshal.Copy(), thenThe IntPtr can be obtained by pinning the memory (remember the managed memory could be moved by the CLR):                GCHandle gch = GCHandle.Alloc(mbyte, GCHandleType.Pinned);
                    IntPtr ptr = gch.AddrOfPinnedObject();
                    // Marshal.Copy here
                    gch.Free();
      

  3.   

      GCHandle retPinned = GCHandle.Alloc(ret);
    改成
      GCHandle retPinned = GCHandle.Alloc(ret, GCHandleType.Pinned);
    ...
      

  4.   

    2楼多谢一直捧场。
    跟一楼说的同一个东西,不过GCHandle gch = GCHandle.Alloc(mbyte, GCHandleType.Pinned);
    黑体部分是不是该改成ret。应给是个结构吧!
      

  5.   

    用Marshal.Copy好像不行Marshal.PtrToStructure  这个可以
      

  6.   

    使用这个方法条件没法相等: 
    static retu GetRetu( byte[] mbyte ) 
            { 
                if (Marshal.SizeOf(typeof(retu)) == mbyte.Length)              // <-- check their sizes do agree. 
                { 
                    GCHandle gch = GCHandle.Alloc(mbyte, GCHandleType.Pinned); 
                    retu r = (retu)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(retu)); 
                    gch.Free();                 return r; 
                } 
                else 
                { 
                    throw new Exception( "no luck, you need to check the manual for the retu struct" ); 
                } 
            } 
    我的数组接回来里面只有11个元素:serialPort1.Read(mbyte5, 0, 11); 
    用16进制表示就是AA F1 89 1 43 81 26 80 3F 5A C0 黑体部分依次是状态,力,电压,电流,时间 我的结构定义: 
    struct retu 
            { 
                public byte a;//数据头 
                public byte b;//下位机地址 
                public byte c;//命令 
                public char d;//状态 
                public float e;//力 
                public float f;//电压 
                public float g;//电流 
                public float h;//运动时间 
                public byte i;//数据长度 
                public byte Verify;//校验 
                public byte j;//数据尾 
            } 所以算下来Marshal.SizeOf(typeof(retu))=28,mbyte.Length==11,这样不可能相等! 
      

  7.   

    现在结构是固定的,也就是Marshal.SizeOf(typeof(retu))=28这个不会变,而数组里长度就不能保证了!可能>28可能<28!
      

  8.   


    你好!谢谢你提供的解决方法,但是还有个问题,我把结构修改了一下: 
    struct retu 

    public byte a;//数据头1 
    public byte b;//下位机地址 
    public byte c;//命令 
    public byte d;//状态1 
    public float e;//力4 
    public float f;//电压 
    public float g;//电流 
    public float h;//运动时间 
    public byte i;//数据长度 
    public byte Verify;//校验 
    public byte j;//数据尾 

    我数了一下,应该是23个字节(float 占4个byte 占1个),但是(Marshal.SizeOf(typeof(retu))却等译24.怎么回事?
    That is because of memory alignment. When data are aligned (say in 4 bytes boundary), data access is fast.In mose cases, you should leave the alignment to its default value. But in some cases, (like network communication), we like data be packed one by one without alignment, in such case we can specify the packing of the structure by saying "Pack=1" (I already mentioned it in one of your post).[StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct retu
    {
      ...You must first make sure about the layout of communication, otherwise you are going nowhere.
      

  9.   

    That is because of memory alignment. When data are aligned (say in 4 bytes boundary), data access is fast. In mose cases, you should leave the alignment to its default value. But in some cases, (like network communication), we like data be packed one by one without alignment, in such case we can specify the packing of the structure by saying "Pack=1" (I already mentioned it in one of your post). [StructLayout(LayoutKind.Sequential, Pack=1)] 
    public struct retu 

      ... 
    You must first make sure about the layout of communication, otherwise you are going nowhere. 
    ===========================================
    我英语不好,看得似懂非懂的。如果[StructLayout(LayoutKind.Sequential, Pack=1)] 会提示“上下文中没有Pack定义”
      

  10.   


    我现在从串口接收到一组返回值存放在数组中: 
    Byte[] mbyte = new Byte[23]; 
    serialPort.Read(mbyte, 0, 23); 
    mbyte中的内容是(16进制表示): 
    AA F1 89 1 0 0 0 0 0 0 0 0 0 0 0 0 3F 31 EB 85 13 A0 FF 请问使用什么方法可以使mbyte和retu对应起来,在程序中直接使用retu.e得出力,retu.f得出电压及其他数据。 怎么实现?

    还是这段:
    using System.Runtime.InteropServices;//...[StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct retu
    {
        //...
    }static retu GetRetu(byte[] mbyte)
    {
        if (Marshal.SizeOf(typeof(retu)) == mbyte.Length)   //<-- check their sizes do agree.
        {
            GCHandle gch = GCHandle.Alloc(mbyte, GCHandleType.Pinned);
            retu r = (retu)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(retu));
            gch.Free();        return r;
        }
        else
        {
            throw new Exception("no luck, you need to check the manual for the retu struct");
        }
    }
      

  11.   

    我现在使用的就是这段,但是加上Pack =1就有下面的提示:错误 2 “System.Runtime.InteropServices.StructLayoutAttribute”并不包含“Pack”的定义去掉Pack =1,Marshal.SizeOf(typeof(retu)) 和mbyte.Length就不相等。前者24后者23.
      

  12.   

    .Net Compact Framework?那你就别管长度了, 只要mbyte.Length <= Marshal.SizeOf(typeof(retu))好了.