Using/converting legacy structs from a stream

S

SethInMI

I am a total newb at .net, and I have not been able to search out a best
practice answer to what must be a common problem.

My app must process binary data from a UDP socket, a MSMQ queue and a file.
In C, the data is in nested structs, with mixed types, floats, ints, char
arrays, int arrays, variable length arrays of structs etc.

My preference would be to access the data in a similar fashion to C, casting
the byte array of received data to the struct I want, and then sending out
the struct when it is time to transmit.

How can I format a struct to be able to mimic legacy structs, especially
with arrays? I see how I can do it for marshalled code, with [ MarshalAs(
UnmanagedType.ByValArray, SizeConst=XX )] attribute, but does that only work
with unmanaged code?

Thanks,

Seth
 
J

John Vottero

SethInMI said:
I am a total newb at .net, and I have not been able to search out a best
practice answer to what must be a common problem.

My app must process binary data from a UDP socket, a MSMQ queue and a
file.
In C, the data is in nested structs, with mixed types, floats, ints, char
arrays, int arrays, variable length arrays of structs etc.

My preference would be to access the data in a similar fashion to C,
casting
the byte array of received data to the struct I want, and then sending out
the struct when it is time to transmit.

How can I format a struct to be able to mimic legacy structs, especially
with arrays? I see how I can do it for marshalled code, with [ MarshalAs(
UnmanagedType.ByValArray, SizeConst=XX )] attribute, but does that only
work
with unmanaged code?

Define your structs using the StructLayout and MarshlAs attributes then use
Marshal.UnsafeAddrOfPinnedArrayElement() and Marshal.PtrToStructure() to
convert from an array of bytes to a managed object. The Marshal class has a
number of useful methods.
 
S

SethInMI

I understand how to at least get started using the Marshal attributes in
defining my struct in C#, but I am still I think missing one step. Does
marshalling work if no unmanaged code or memory is accessed?

here is my pseudo code, where myStruct is defined using LayoutSequential and
appropriate Marshalling attributes to mimic the layout of legacy C struct.

Byte[] RawData = sock.Receive(ref RawAddr);
If (RawData.Length == Marshal.SizeOf(myStruct) {
Convert RawData into myStruct (using marshalling? just a cast?)
}

John Vottero said:
SethInMI said:
I am a total newb at .net, and I have not been able to search out a best
practice answer to what must be a common problem.

My app must process binary data from a UDP socket, a MSMQ queue and a
file.
In C, the data is in nested structs, with mixed types, floats, ints, char
arrays, int arrays, variable length arrays of structs etc.

My preference would be to access the data in a similar fashion to C,
casting
the byte array of received data to the struct I want, and then sending out
the struct when it is time to transmit.

How can I format a struct to be able to mimic legacy structs, especially
with arrays? I see how I can do it for marshalled code, with [ MarshalAs(
UnmanagedType.ByValArray, SizeConst=XX )] attribute, but does that only
work
with unmanaged code?

Define your structs using the StructLayout and MarshlAs attributes then use
Marshal.UnsafeAddrOfPinnedArrayElement() and Marshal.PtrToStructure() to
convert from an array of bytes to a managed object. The Marshal class has a
number of useful methods.
 
J

John Vottero

SethInMI said:
I understand how to at least get started using the Marshal attributes in
defining my struct in C#, but I am still I think missing one step. Does
marshalling work if no unmanaged code or memory is accessed?

here is my pseudo code, where myStruct is defined using LayoutSequential
and
appropriate Marshalling attributes to mimic the layout of legacy C struct.

Byte[] RawData = sock.Receive(ref RawAddr);
If (RawData.Length == Marshal.SizeOf(myStruct) {
Convert RawData into myStruct (using marshalling? just a cast?)
}

To convert RawData into myStruct, you would do something like:

IntPtr adr = Marshal.UnsafeAddrOfPinnedArrayElement(RawData, 0);
MyStruct myStruct = Marshal.PtrToStructure(adr, typeof(MyStruct));

When you use the LayoutSequential and Marshaling attributes, you aren't
actually changing the structure, you're just providing instructions that are
used when marshaling the structure to/from unmanaged bytes.
 
S

SethInMI

Thanks John.

You mentioned UnsafeAddrOfPinnedArrayElement in your first post, I just
didn't pick up how to use it.

John Vottero said:
SethInMI said:
I understand how to at least get started using the Marshal attributes in
defining my struct in C#, but I am still I think missing one step. Does
marshalling work if no unmanaged code or memory is accessed?

here is my pseudo code, where myStruct is defined using LayoutSequential
and
appropriate Marshalling attributes to mimic the layout of legacy C struct.

Byte[] RawData = sock.Receive(ref RawAddr);
If (RawData.Length == Marshal.SizeOf(myStruct) {
Convert RawData into myStruct (using marshalling? just a cast?)
}

To convert RawData into myStruct, you would do something like:

IntPtr adr = Marshal.UnsafeAddrOfPinnedArrayElement(RawData, 0);
MyStruct myStruct = Marshal.PtrToStructure(adr, typeof(MyStruct));

When you use the LayoutSequential and Marshaling attributes, you aren't
actually changing the structure, you're just providing instructions that are
used when marshaling the structure to/from unmanaged bytes.
 
B

Ben Voigt [C++ MVP]

SethInMI said:
I am a total newb at .net, and I have not been able to search out a
best practice answer to what must be a common problem.

My app must process binary data from a UDP socket, a MSMQ queue and a
file. In C, the data is in nested structs, with mixed types, floats,
ints, char arrays, int arrays, variable length arrays of structs etc.

My preference would be to access the data in a similar fashion to C,
casting the byte array of received data to the struct I want, and
then sending out the struct when it is time to transmit.

How can I format a struct to be able to mimic legacy structs,
especially with arrays? I see how I can do it for marshalled code,
with [ MarshalAs( UnmanagedType.ByValArray, SizeConst=XX )]
attribute, but does that only work with unmanaged code?


Use the BitConverter class to convert each member, one at a time.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top