0

I am trying to serialize a structure to disk as raw bytes. This is a (simplified)version of it.

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class TestData :BaseStructure
{
    public byte[] bytes = new byte[]{65,66,67}; // this doesn't write ABC as expected
}

A write function uses ConvertStructureToBytes method to convert this to a byte array and a binary writer then writes it.

    public void Write(BaseStructure baseStructure)
    {
        binaryWriter.Write(ConvertStructureToBytes(baseStructure));
    }

The ConvertStructureToBytes section

 public byte[] ConvertStructureToBytes(BaseStructure baseStructure)
    {
        int len = Marshal.SizeOf(baseStructure);
        byte[] arr = new byte[len];

        IntPtr ptr = Marshal.AllocHGlobal(len);
        Marshal.StructureToPtr(baseStructure, ptr,false);
        Marshal.Copy(ptr, arr, 0, len);

        Marshal.FreeHGlobal(ptr);
        return arr;
    }

If I replace the bytes line to

public byte byte = 65; // This now writes an A , as expected

I have tried

public byte[] bytes = Encoding.ASCII.GetBytes("ABC"); //doesn't work either

This probably has something to do with the ConvertStructureToBytes function , it isn't treating the byte array as it should.

What do I need to do to be able to write 'ABC' successfully?

2
  • I have edited your title. Please see, "Should questions include “tags” in their titles?", where the consensus is "no, they should not". Commented Sep 12, 2014 at 21:04
  • What is BaseStructure? Your TestData class inherits from it, but you are not serialising a TestData instance but a BaseStructure instance, which is not aware of the data declared in the TestData class. Commented Sep 12, 2014 at 21:10

3 Answers 3

3

Several problems. First your structure declaration is not correct, you have to in-line the array so it no longer a pointer:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class TestData {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public byte[] bytes = new byte[] { 65, 66, 67 };
}

Then your ConvertStructureToBytes() method is not correct, it is only ever going to marshal BaseStructure. You need to make it generic:

public static byte[] ConvertStructureToBytes<T>(T baseStructure) {
    // rest the same...
}

Do note the kind of trouble you can get into with this approach, it most certainly is not a universal way to marshal data. Only very specific classes can be serialized this way. That [MarshalAs] attribute is of course very painful to maintain. You might as well use binary serialization.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, this WORKS! Yay... I am actually writing raw bytes for ISO9660 structure and the classes involved are directories,files and path tables, all predefined and the fields, such as bytes above wont' change. So I think this solution works fine for me :)
Okay, a fixed set of structure declarations is fine. Please close your question.
1

Change the class definition to this and try it:

StructLayout(LayoutKind.Sequential, Pack = 1)]
public class TestData :BaseStructure
{
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public byte[] bytes = new byte[]{65,66,67}; 
}

Comments

0

Try this:

byte[] bytes = Encoding.ASCII.GetBytes("ABC").ToArray();

Or, after I tested that. Maybe you mean this:

bytes = new byte[] { 65, 66, 67 };
string test = Encoding.UTF8.GetString(bytes).ToString();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.