Declare array size in Struct?

R

robert.waters

I have to parse a binary file having a number of fixed records, each
record containing datas in fixed positions. I would like to parse
this binary file into an array of structures having members that
represent those fields, so that I can access the records in a
meaningful way.
Using C, I would have defined a struct that I could cast a byte array
into, which held exactly one of these fixed records. The struct would
be defined as such:
struct rec {
char index[1] ;
char padding[50];
char name[28];
};
No big deal, (rec)char_array;.

I tried to do something similar in C#, and I am getting an error
telling me that:
"Array size cannot be specified in a variable declaration"

How might I create a data structure with fixed-size members at design
time?
Do I really have to encapsulate this into a class that contains logic
to parse the record sequentially when it's instantiated?

Thanks.
 
K

Kerem Gümrükcü

Hi Robert,

i think, you are looking for this (PInvoke Style):

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)
public struct rec
{
[MarshalAs(UnmanagedType.LPStr,SizeConst=1)]
string index; //could also be a byte
[MarshalAs(UnmanagedType.LPStr,SizeConst=50)]
string padding;//could also be a byte
[MarshalAs(UnmanagedType.LPStr,SizeConst=28)]
string name;//could also be a byte
}

then you go like this:

rec your_rec = (rec)
Marshal.PtrToStructure(ptrPointerToYourBytesBlockOfMemory,typeof(rec));
MessageBox.Show(your_rec.name);

Regards

Kerem

--
 
R

robert.waters

Hi Robert,

i think, you are looking for this (PInvoke Style):

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)
public struct rec
{
    [MarshalAs(UnmanagedType.LPStr,SizeConst=1)]
    string index; //could also be a byte
    [MarshalAs(UnmanagedType.LPStr,SizeConst=50)]
    string padding;//could also be a byte
    [MarshalAs(UnmanagedType.LPStr,SizeConst=28)]
    string name;//could also be a byte

}

then you go like this:

rec your_rec = (rec)
Marshal.PtrToStructure(ptrPointerToYourBytesBlockOfMemory,typeof(rec));
MessageBox.Show(your_rec.name);

Regards

Kerem

Thank you, that's exactly what I needed.
 
R

robert.waters

Hi Robert,

i think, you are looking for this (PInvoke Style):

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)
public struct rec
{
    [MarshalAs(UnmanagedType.LPStr,SizeConst=1)]
    string index; //could also be a byte
    [MarshalAs(UnmanagedType.LPStr,SizeConst=50)]
    string padding;//could also be a byte
    [MarshalAs(UnmanagedType.LPStr,SizeConst=28)]
    string name;//could also be a byte

}

then you go like this:

rec your_rec = (rec)
Marshal.PtrToStructure(ptrPointerToYourBytesBlockOfMemory,typeof(rec));
MessageBox.Show(your_rec.name);

I have a problem: I get an 'attempted to read protected memory"
exception.
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
public struct PbEntry // size=385b
{
[MarshalAs(UnmanagedType.LPStr,SizeConst=1)]
string index;
[MarshalAs(UnmanagedType.LPStr,SizeConst=5)]
string nameHeader;
[MarshalAs(UnmanagedType.LPStr,SizeConst=123)]
string contactName;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 11)]
string numsHeader;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 49)]
string cellNumber;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 49)]
string homeNumber;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 49)]
string workNumber;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 49)]
string otherNumber1;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 49)]
string otherNumber2;
}

...... program and FileStream ('fs') set-up .....

byte[] pbData = new byte[385];
fs.Read(pbData, 0, 385);
// pbData is now populated correctly
PbEntry pb=new PbEntry();
IntPtr ptr = Marshal.AllocHGlobal(pbData.Length);
try
{
Marshal.Copy(pbData, 0, ptr, pbData.Length);
pb = (PbEntry)Marshal.PtrToStructure(ptr,
typeof(PbEntry)); // exception happens here
Console.WriteLine(pb.ToString());
}
finally
{
Marshal.FreeHGlobal(ptr);
}

Any reason why that is protected memory?

Thanks!
 
R

robert.waters

Hi Robert,
i think, you are looking for this (PInvoke Style):
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)
public struct rec
{
    [MarshalAs(UnmanagedType.LPStr,SizeConst=1)]
    string index; //could also be a byte
    [MarshalAs(UnmanagedType.LPStr,SizeConst=50)]
    string padding;//could also be a byte
    [MarshalAs(UnmanagedType.LPStr,SizeConst=28)]
    string name;//could also be a byte

then you go like this:
rec your_rec = (rec)
Marshal.PtrToStructure(ptrPointerToYourBytesBlockOfMemory,typeof(rec));
MessageBox.Show(your_rec.name);

I have a problem: I get an 'attempted to read protected memory"
exception.
    [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
    public struct PbEntry  // size=385b
    {
        [MarshalAs(UnmanagedType.LPStr,SizeConst=1)]
        string index;
        [MarshalAs(UnmanagedType.LPStr,SizeConst=5)]
        string nameHeader;
        [MarshalAs(UnmanagedType.LPStr,SizeConst=123)]
        string contactName;
        [MarshalAs(UnmanagedType.LPStr, SizeConst = 11)]
        string numsHeader;
        [MarshalAs(UnmanagedType.LPStr, SizeConst = 49)]
        string cellNumber;
        [MarshalAs(UnmanagedType.LPStr, SizeConst = 49)]
        string homeNumber;
        [MarshalAs(UnmanagedType.LPStr, SizeConst = 49)]
        string workNumber;
        [MarshalAs(UnmanagedType.LPStr, SizeConst = 49)]
        string otherNumber1;
        [MarshalAs(UnmanagedType.LPStr, SizeConst = 49)]
        string otherNumber2;
     }

..... program and FileStream ('fs') set-up .....

                byte[] pbData = new byte[385];
                fs.Read(pbData, 0, 385);
                // pbData is now populated correctly
                PbEntry pb=new PbEntry();
                IntPtr ptr = Marshal.AllocHGlobal(pbData.Length);
                try
                {
                    Marshal.Copy(pbData, 0, ptr, pbData.Length);
                    pb = (PbEntry)Marshal.PtrToStructure(ptr,
typeof(PbEntry)); // exception happens here
                    Console.WriteLine(pb.ToString());
                }
                finally
                {
                    Marshal.FreeHGlobal(ptr);
                }

Any reason why that is protected memory?

Thanks!

Replacing UnmanagedType.LPStr with UnmanagedType.ByValTStr for each
struct member fixed this problem.
Does anyone have any idea why?
Note: the data inside the records had many nulls (\0), which I figured
wouldn't be a problem because they typically follow strings of non-
null characters, and so would fit the model of 'null-terminated ANSI
character string'.
Thank you for any input that would help.
 

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