By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,712 Members | 1,591 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,712 IT Pros & Developers. It's quick & easy.

arrays, structs, pointers, casting - help!

P: n/a
i am new to c# so if this is a trivial problem, forgive me! i've
searched the web and after 2 days still cannot solve it. i am
converting a c++ application to c# - the problem code is listed below.
the c++ code uses a byte array (msg[256]) to hold a serial message.
since the message can be of different layouts, the array is cast to the
appropriate layout "type" (struct SERIAL_CAN_MSG_TYPE, in this
example). to complicate things, there is an array at the end of the
SERIAL_CAN_MSG_TYPE struct, data[], which can hold variable data types
(byte, ushort, and uint) -AND- can be of variable length (more than 2
elements). with that said, here's the c++ code:

---------- start c++ code -------------
typedef unsigned char INT_8U;
typedef unsigned short int INT_16U;
typedef short int INT_16;
....
typedef struct
{
INT_8U priority;
INT_16 dlc;
INT_8U messageType;
INT_8U channel;
INT_8U data[2];
}SERIAL_CAN_MSG_TYPE;
....
INT_8U msg[256];
SERIAL_CAN_MSG_TYPE* msgPtr;
msgPtr = (SERIAL_CAN_MSG_TYPE*)&(msg[0]);
....
// uses casting to assign a ushort to the byte array (data)
for(i = 0; i < 64; i++)
{
*((INT_16U *)&msgPtr->data[i*4]) = spoolChannel[i].address;
}
------- end c++ code --------

..... and here's my attempt at converting to c#:

----------- start c# code ------------
[StructLayout(LayoutKind.Explicit)]
unsafe public struct SERIAL_CAN_MSG_TYPE
{
[FieldOffset(0)]public byte priority;
[FieldOffset(1)]public short dlc;
[FieldOffset(3)]public byte messageType;
[FieldOffset(4)]public byte channel;
// to take care of diff element types in 1 array,
// since i can't cast on left-hand side of equation
[FieldOffset(5)]public byte [] dataBytePtr;
[FieldOffset(5)]public ushort [] dataUshortPtr;
[FieldOffset(5)]public uint [] dataUintPtr;
};
....
byte [] msg = new byte[256];
fixed(SERIAL_CAN_MSG_TYPE * msgPtr = (SERIAL_CAN_MSG_TYPE*) msg[0])
{
...
for(i = 0; i < 64; i++)
{
// assigns a ushort to the data array using ushort ptr
msgPtr->dataUshortPtr[i] = spoolChannel[i].address;
}
...
}
----------- end c# code --------

above c# code produces error:
"Cannot take the address or size of a variable of a managed
type('SERIAL_CAN_MSG_TYPE')"
on the "fixed" line.

i've read that in c#, a pointer is not permitted to point to a struct
that contains references (arrays). i'm sure it has something to do
with managed/unmanaged code, but i don't understand it deep enough to
figure out a solution!

thanks for any help...

Nov 17 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
oops, forgot the "&" in the c# line:
fixed(SERIAL_CAN_MSG_TYPE * msgPtr = (SERIAL_CAN_MSG_TYPE*) &msg[0])
kelli

Nov 17 '05 #2

P: n/a
Doesn't it work for you?

[StructLayout(LayoutKind.Explicit)]
unsafe public struct SERIAL_CAN_MSG_TYPE
{
[FieldOffset(0)]public byte priority;
[FieldOffset(1)]public short dlc;
[FieldOffset(3)]public byte messageType;
[FieldOffset(4)]public byte channel;
// to take care of diff element types in 1 array,
// since i can't cast on left-hand side of equation
[FieldOffset(5)]public byte [] dataBytePtr;
[FieldOffset(5)]public ushort [] dataUshortPtr;
[FieldOffset(5)]public uint [] dataUintPtr;
};

public unsafe void test()
{
byte [] msg = new byte[256];

fixed(byte *msgPtr = msg)
{
SERIAL_CAN_MSG_TYPE newStruct = new SERIAL_CAN_MSG_TYPE();

Marshal.PtrToStructure((IntPtr) msgPtr, newStruct);

fixed(ushort *ushortPtr = newStruct.dataUshortPtr)
{
for(int i = 0; i < 64; i++)
{
// assigns a ushort to the data array using ushort ptr
*(ushortPtr + i) = 0;//spoolChannel[i].address;
}
}
}
}

It doesn't cast you msg[256] into a SERIAL_CAN_MSG_TYPE, PtrToStructure
(basically a memcpy) fill the new struct and from there work with it.

Is it mandatory to modificate the values on the original msg[256] or can you
use the newStruct???

Gustavo.

"kelli" <k-******@tamu.edu> wrote in message
news:11**********************@g44g2000cwa.googlegr oups.com...
oops, forgot the "&" in the c# line:
fixed(SERIAL_CAN_MSG_TYPE * msgPtr = (SERIAL_CAN_MSG_TYPE*) &msg[0])
kelli

Nov 17 '05 #3

P: n/a
gustavo - thank you so much - it does seem to work (compiles anyway!).

you may be right - i think i can fill the structure, then use
Marshal.Copy (maybe?) to get the data into a byte array which is passed
to the next function.

Nov 17 '05 #4

P: n/a
If you need back the array then may be you can use

Marshal.StructureToPtr(newStruct, (IntPtr) msgPtr, true);

Marshal.Copy also should work, but I don't know if it could have some
problem.

Gustavo.
"kelli" <k-******@tamu.edu> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
gustavo - thank you so much - it does seem to work (compiles anyway!).

you may be right - i think i can fill the structure, then use
Marshal.Copy (maybe?) to get the data into a byte array which is passed
to the next function.

Nov 17 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.