locked
" Object contains non-primitive or non-blittable data" error RRS feed

  • Question

  • I have the following structure that I need to marshal:

            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct  SItuLongEmailMsg

            {

                public byte appId;

                public byte msgType;

                public byte id;

                public byte dstAddr1;

                public byte dstAddr2;

                public byte dstAddr3;  

                public UInt16 size;

                public byte protocol;

                public byte seqNum;

                public byte msgHeader;

                public byte messageType;

                public byte priority;

                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2048)]

                public byte[] text;  

            };

    When I call:

    GCHandle pinStructure = GCHandle.Alloc(o, GCHandleType.Pinned);

    Where o is the structure I‘m working with, I get the ArgumentException:  Object contains non-primitive or non-blittable data error.
    I know the issue is the byte[] text but so far I am at a lose as to how to do this.

    Thanks,
    Richard Sienkiewicz
    High Fidelity Engineering

    Wednesday, July 9, 2008 8:19 PM

Answers

  •  

    Finally figured it out. I needed to do this, referencing the first post’s struct:

    SItuLongEmailMsg msg = newSItuLongEmailMsg();

    // set members

     

    msg.text = new byte[2048];

    // assign to msg.text

     

    int msgSize = Marshal.SizeOf(msg);

    IntPtr ptr = Marshal.AllocHGlobal(msgSize);

    Marshal.StructureToPtr(msg, ptr, true);

    byte[] dataOut = new byte[msgSize];

    Marshal.Copy(ptr, dataOut, 0, msgSize);

     

    Then send dataOut to the serial port.

     

    Thanks.

    Thursday, July 10, 2008 2:25 PM

All replies

  • you can read about bittable and nobittable types here. the problem is with your byte[] text. try to transform it in a bittable type for your code to work
    Lucian Baciu, MCTS, http://studentclub.ro/lucians_weblog
    Thursday, July 10, 2008 7:03 AM
  •  

    That link said one dimensional arrays of blittable types are also a blittable type. So a complex type like a  byte[] is a blittable type, yet it doesn’t work.

    What I’m trying to do is convert a struct to a byte[] to send over the serial port. I can convert  a byte[] sent from the serial port to a struct this way (dataIn is a byte[]) :

    GCHandle pinnedPacket = GCHandle.Alloc(dataIn, GCHandleType.Pinned);

    MyStruct s =(MyStruct)Marshal.PtrToStructure(pinnedPacket.AddrOfPinnedObject(), typeof(MyStruct));

    pinnedPacket.Free();

     

    where MyStruct looks like this:

     

    [StructLayout(LayoutKind.Sequential, Pack = 1)]

    public struct MyStruct

    {

          public UInt16 a;

          public byte b;

          public byte c;

          public byte d;

          [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]

          public byte[] e;

    };

     

    But I can seem to figure out how to do it in the reverse, going from a struct with an array to a byte[].

    Thursday, July 10, 2008 1:40 PM
  •  

    Finally figured it out. I needed to do this, referencing the first post’s struct:

    SItuLongEmailMsg msg = newSItuLongEmailMsg();

    // set members

     

    msg.text = new byte[2048];

    // assign to msg.text

     

    int msgSize = Marshal.SizeOf(msg);

    IntPtr ptr = Marshal.AllocHGlobal(msgSize);

    Marshal.StructureToPtr(msg, ptr, true);

    byte[] dataOut = new byte[msgSize];

    Marshal.Copy(ptr, dataOut, 0, msgSize);

     

    Then send dataOut to the serial port.

     

    Thanks.

    Thursday, July 10, 2008 2:25 PM
  • Hi,

    I have the same situation and try to implement this solution but seems that I am missing some thing.

    Following is the structure:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct TSymBuff
    {
      public int length;
      [MarshalAs(UnmanagedType.ByValArray)]
      public byte[] buffer;
    }

    I need to pass it to Delphi DLL. The DLL will update the structure which will be used later in my C# code.

    int actualLength = 5;
    TSymBuff s = new TSymBuff();
    s.buffer = new byte[actualLength];
    
    int msgSize = Marshal.SizeOf(s);
    IntPtr ptr = Marshal.AllocHGlobal(msgSize);
    Marshal.StructureToPtr(s, ptr, false);
    
    //actualLength = SymDecipher("SEED", key.Length, key, msg, ref s); // passed the structure by by reference
    actualLength = SymDecipher("SEED", key.Length, key, msg, s); // passed the structure by value
    
    byte[] dataOut = new byte[msgSize];
    Marshal.Copy(ptr, dataOut, 0, msgSize);

    At this point, I didn't get the values in dataOut. 

    Please help me. I don't know where I am doing wrong. Many thanks in advance.

    Regards.

    Thursday, June 3, 2010 2:33 PM
  • The default marshaler cannot handle variable length arrays in structs. You need to specify a SizeConst parameter for the MarshalAs attribute, or copy the structure yourself.
    Thursday, June 3, 2010 5:32 PM