Posts
7
Comments
2
Trackbacks
0
Unmanaged arrays in C# structs
I am creating a Memory Mapped File (MMF) that will act like a circular buffer because it will store "live" 100msec data from a PLC.  The controls engineer wanted to send the data to me as tag arrays.  So, to mimic these tag arrays, I decided to create a structure the reflects these tag arrays. 

There are ten arrays in the structure. 

The first array is an array of two short integers (16-bits) that contain a write and read pointer.
The next three array is an array of 1024 bytes, an array of 1024 short integers and an array of 1024 floats.  This set of three arrays is repeated three times.

A structLayout attribute is used to place these arrays in sequential order and I specify the size so that I can reserve that amount of space on the disk for the MMF when it is created.  Each array is marshalled as an  UnmanagedType.ByValArray. 

Here is the structure as I first created it:

[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 150532)]
public struct strL1CmnRec
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.I2)] public short[] shtL1Ptrs;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = UnmanagedType.U1)] public byte[] byEntryBool;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = UnmanagedType.I2)] public short[] shtEntryInts;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = UnmanagedType.R4)] public float[] sngEntryReals;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = UnmanagedType.U1)] public byte[] byProcBool;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = UnmanagedType.I2)] public short[] shtProcInts;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = UnmanagedType.R4)] public float[] sngProcReals;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = UnmanagedType.U1)] public byte[] byDelvBool;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = UnmanagedType.I2)] public short[] shtDelvInts;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = UnmanagedType.R4)] public float[] sngDelvReals;
}

To access this structure and its arrays, I declared this variable:

strL1CmnRec L1CRec;

I then attempted to write into one the arrays as follows:

L1CRec.shtL1Ptrs[0] = i;
L1CRec.shtL1Ptrs[1] = 0;

And, when i was attempted to be placed into shtL1Ptrs[0], I received a runtime error because shtL1Ptrs[0] was null!

What to do? What to do?


It turns out that in a C# struct, the arrays are declared but its memory is not allocated. So I wrote a create method to allocate memory
for each array in the struct. The create method is part of the C# struct.

public static strL1CmnRec create()
{
return new strL1CmnRec
{
shtL1Ptrs = new short[2],
byEntryBool = new byte[1024],
shtEntryInts = new short[1024],
sngEntryReals = new float[1024],
byProcBool = new byte[1024],
shtProcInts = new short[1024],
sngProcReals = new float[1024],
byDelvBool = new byte[1024],
shtDelvInts = new short[1024],
sngDelvReals = new float[1024]
};
}


So, now to access these arrays, I first declared the variable:

strL1CmnRec L1CRec;

then I call the create function.  I place this in the constructor of the class that is using this structure:

L1CRec = strL1CmnRec.create();
I can now successfully access the arrays in the struct. 

 
posted on Thursday, July 09, 2009 5:13 PM Print
Comments
Gravatar
# re: Arrays in C# structs
EnderWiggin
7/10/2009 7:59 AM
That's good to know.
Sometimes we are so pampered by the framework we forget things like that.
Oh, "Unmanaged Arrays in C# Structs" is a lot more helpful and interesting title.

Post Comment

Title *
Name *
Email
Url
Comment *  
 
News