Here is the C code simplified. The actual structure is much more complex.
| // -- Message File Structure -- |
| struct message_struct{ // Message Structure |
| char mname[20]; // Message Name |
| char mattr; // Message Slot Used flag |
| struct { // Page // Page Structure |
| int duration; // Duration |
| char stext[201]; // Scroll Buffer |
| struct { // Line // Line Structure |
| char csize; // Char Size |
| char mchar[31]; // Line Characters |
| } mline[8]; // # of Lines |
| } mpage[10]; // # of Pages |
| } message; |
Then to access the structure
message.mpage[0].mline[0].mchar[0] = 'A';
AlanPosted Dec 2, 2008, 6:07 AM
When you 'new' a struct in C#, it initializes all value type fields to their default values (zero for numeric types, false for bool etc). However, reference type fields such as strings and arrays are set to null. You therefore need to explicitly create objects of those types:
message myMessage = new message();
myMessage.mname = new char[20];
myMessage.mname[0] = 'A';
Console.WriteLine(myMessage.mname[0]); // A
RanandarPosted Dec 2, 2008, 3:14 PM
AlanPosted Dec 2, 2008, 2:16 PM
Yes, you have to create the arrays in each struct so your code looks good now.
I see you've also removed the attributes which you only need if you're going to use the struct(s) for interop with C code.
Incidentally, the reason we have to go through this rigmarole is that array fields contained within a struct are not stored inline in C# as they are in C. Instead the C# struct contains a pointer to where the array is stored on the heap.
Just as a matter of interest, you can use inline C-style arrays in unsafe code (see link below) but this wouldn't have helped here as this feature can only be used for arrays of primitive types, not arrays of user defined structs.
http://msdn.microsoft.com/en-us/library/zycewsya(VS.80).aspx
RanandarPosted Dec 2, 2008, 11:28 AM
This is what I have come up with...
public struct message_struct
{
public string name; // Message Name
public int pattr2;
public message_page[] pages;
}
public struct message_page
{
public int duration; // Duration
public string stext; // Scroll Buffer
public message_line[] lines;
}
public struct message_line
{
public int csize; // Char Size
public string mchar; // Line Characters
}
public message_struct myMessage = new message_struct();
...
public Form1()
{
InitializeComponent();
myMessage.pages = new message_page[10];
for (int i = 0; i < 10; i++) myMessage.pages[i].lines = new message_line[8];
}
RanandarPosted Dec 2, 2008, 10:32 AM
myMessage.mpage[0] = new page();
// Object reference not set to an instance of an object
myMessage.mpage[0].stext = new char[20];
// Object reference not set to an instance of an object
RanandarPosted Dec 1, 2008, 9:06 PM
When I try:
message myMessage = new message();
myMessage.mname[0] = 'A';
I get:
"Object reference not set to an instance of an object."
AlanPosted Dec 1, 2008, 7:07 PM
It should be possible to represent that struct in C# by building it up in layers.
Without any other info, I'd have come up with this for interop purposes:
[StructLayout(LayoutKind. Sequential, CharSet=CharSet.Ansi)]
public struct message
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string mname;
public char mattr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public page[] mpage;
}
[StructLayout(LayoutKind. Sequential, CharSet=CharSet.Ansi)]
public struct page
{
public int duration;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 201)]
public string stext;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public line[] mline;
}
[StructLayout(LayoutKind. Sequential, CharSet=CharSet.Ansi)]
public struct line
{
public char csize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 31)]
public string mchar;
}
However, your example suggests you might want the individual characters of the strings to be writable from C#. If that's the case, you'll need to use char arrays rather than strings:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct message
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] mname;
public char mattr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public page[] mpage;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct page
{
public int duration;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 201)]
public char[] stext;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public line[] mline;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct line
{
public char csize;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)]
public char[] mchar;
}