Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Convert a struct to a Char[]

Status
Not open for further replies.

spas

Programmer
Sep 11, 2002
20
0
0
I'm trying to figure out how to convert a struct (or class) to a char[] representation of the struct. I've got a struct that has several short and byte field definitions that needs to be concatenated with another struct and sent to unmanaged code.

I think that I should use an explicit operator, but don't know how to copy the information in the struct to the new char[].

Any ideas?
Thanks, Scott
 
Well, I answered my own question, so I thought I'd share the asnwer with you.

First, don't use a char[] array. In .NET the char's are double byte.

Use a byte[] array.

Secondly, you have to use marshal code to get the job done, but it is actually pretty easy if you are dealing with base data types within the struct. (i.e. not strings -- although, from the examples that I've seen that wouldn't be that difficult)

I also changed my struct to a class that looked something like the following:

Code:
public class mySpec {
  short field1;
  short field2;
  byte  field3;
  int   reserved4;
  byte  field5;
  short field6; 
}

After creating this class structure definition, I added a method called ToByteArray which is what uses the marshal code.

Code:
public byte[] ToByteArray()
{
  IntPtr ptrDef = Marshal.AllocCoTaskMem(16);

  Marshal.WriteInt16(ptrDef,0,this.field1);
  Marshal.WriteInt16(ptrDef,2,this.field2);
  Marshal.WriteInt16(ptrDef,4,this.field3;
  Marshal.WriteInt32(ptrDef,5,this.Reserved4);
  Marshal.WriteByte(ptrDef,9,this.field5);
  Marshal.WriteByte(ptrDef,11,this.field6);

  byte[] myChars = new byte[12];
  Marshal.Copy(ptrDef,myChars,0,12);
  Marshal.FreeCoTaskMem(ptrDef);
  return myChars;
}

The first line of the method uses the Marshal method AllocCoTaskMem to create an unmanaged memory location to stuff the structure into.
The next 6 lines uses an overloaded verion of WriteInt16, WriteByte, and WriteInt32 to write the specified field to a specified offset from the beginning of the ptrDef pointer.

Next I allocate 12 bytes in an array and use the Marshal.Copy method to copy the bytes from the ptrDef unmanaged memory location to a managed memory byte[] array and return that array. Now my structure is nicely packaged into a byte array.


Why use this?
Glad you asked. I am working on a object to wrap the Btrieve database API. To define a file, you need to pass the Btrieve BTRCALL function a byte array with a File Descriptor, followed by the Key Descriptors for the file.

Not having an example for the above, took some wrestling to get it figured out and working. As an alternative, you could use the StrutureToPtr to copy the whole structure to the unmanaged memory, but then you have to add attributes to the Class definition to define the order for the fields to keep .NET from rearranging them.

Well, I hope this helps someone.
Scott
 
Hi,
I tried your way, but I got many exceptions.
I want to suggest you another way that worked fine and you don't need to use Marshal:
for example this struct: (header of a bitmap file)
struct BitmapFileHeader
{
public ushort bfType;
public int bfSize;
public ushort bfReserved1;
public ushort bfReserved2;
public int bfOffBits;
public static int Length = 14;

public byte[] ToByteArray()
{
byte[] ByteArray = new byte[Length];
BitConverter.GetBytes(bfType).CopyTo(ByteArray,0);
BitConverter.GetBytes(bfSize).CopyTo(ByteArray, 2);
BitConverter.GetBytes(bfReserved1).CopyTo(ByteArray, 6);
BitConverter.GetBytes(bfReserved2).CopyTo(ByteArray, 8);
BitConverter.GetBytes(bfOffBits).CopyTo(ByteArray, 10);
return ByteArray;
}

public void FromByteArray(byte[] ByteArray)
{
bfType = BitConverter.ToUInt16(ByteArray, 0);
bfSize = BitConverter.ToInt32(ByteArray, 2);
bfReserved1 = BitConverter.ToUInt16(ByteArray, 6);
bfReserved2 = BitConverter.ToUInt16(ByteArray, 8);
bfOffBits = BitConverter.ToInt32(ByteArray, 10);
}
};

I used it to read and write this structure to a file.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top