Converting C struct to C#

  • Thread starter Thread starter VMI
  • Start date Start date
V

VMI

How can I convert the following C struct into a C# struct? The struct is
sent to an API function (written in C) as parameter, and the function fills
it with data. I tried to convert it and most of it works but the data in the
foot struct is not correct (I believe it's a conversion problem between C#
and C).
The class I created in C# (from the struct) is at the bottom.

typedef struct
{
char iadl1[50+1];
char ictyi[50+1];
char auto_zone_ind;
char retcc;
struct {
char a;
char b;
char c;
char d;
char rsvd3[6];
} foot;
} ZIP4_PARM;

*****************************
/* My struct converted */
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ZIP4_PARM
{
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string iadl1;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string ictyi;
public char auto_zone_ind;
public char retcc;
public footer foot;
public struct footer
{
public char a;
public char b;
public char c;
public char d;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
public string rsvd3;
}
}
 
VMI,

The problem comes from using a character type. In .NET this is a
unicode character, and not an 8-bit ANSI character like it is in C. You can
declare the type two ways:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ZIP4_PARM
{
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string iadl1;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string ictyi;
public byte auto_zone_ind;
public byte retcc;
public footer foot;
public struct footer
{
public byte a;
public byte b;
public byte c;
public byte d;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
public string rsvd3;
}
}

The other way you can declare it is by declaring all of the character
fields as strings, and then tagging them so they are marshaled as
ByValTStrs, with a size of one. Either way should work.

Hope this helps.
 
Thanks. IT worked perfectly.

Nicholas Paldino said:
VMI,

The problem comes from using a character type. In .NET this is a
unicode character, and not an 8-bit ANSI character like it is in C. You can
declare the type two ways:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ZIP4_PARM
{
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string iadl1;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string ictyi;
public byte auto_zone_ind;
public byte retcc;
public footer foot;
public struct footer
{
public byte a;
public byte b;
public byte c;
public byte d;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
public string rsvd3;
}
}

The other way you can declare it is by declaring all of the character
fields as strings, and then tagging them so they are marshaled as
ByValTStrs, with a size of one. Either way should work.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

VMI said:
How can I convert the following C struct into a C# struct? The struct is
sent to an API function (written in C) as parameter, and the function fills
it with data. I tried to convert it and most of it works but the data in the
foot struct is not correct (I believe it's a conversion problem between C#
and C).
The class I created in C# (from the struct) is at the bottom.

typedef struct
{
char iadl1[50+1];
char ictyi[50+1];
char auto_zone_ind;
char retcc;
struct {
char a;
char b;
char c;
char d;
char rsvd3[6];
} foot;
} ZIP4_PARM;

*****************************
/* My struct converted */
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ZIP4_PARM
{
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string iadl1;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string ictyi;
public char auto_zone_ind;
public char retcc;
public footer foot;
public struct footer
{
public char a;
public char b;
public char c;
public char d;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
public string rsvd3;
}
}
 
Hi,

*****************************
/* My struct converted */
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ZIP4_PARM
{
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string iadl1;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string ictyi;
public char auto_zone_ind;
public char retcc;
public footer foot;
[....]
public struct footer
{
public char a;
public char b;
public char c;
public char d;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
public string rsvd3;
}
}

You must *also* prefix the child-struct with
[StructLayout(LayoutKind.Sequential, CharSet=Charset.Ansi)]. Other then
that I do not see any problems...


HTH,
greetings
 
Thanks for the info. It worked perfectly.
I also posted another message for help on how to convert another C-struct
(with array) to C-sharp. I'd really appreciate it if you could take a look
at it to see if you have an idea on how to solve it.

Thanks.

BMermuys said:
Hi,

*****************************
/* My struct converted */
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ZIP4_PARM
{
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string iadl1;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string ictyi;
public char auto_zone_ind;
public char retcc;
public footer foot;
[....]
public struct footer
{
public char a;
public char b;
public char c;
public char d;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
public string rsvd3;
}
}

You must *also* prefix the child-struct with
[StructLayout(LayoutKind.Sequential, CharSet=Charset.Ansi)]. Other then
that I do not see any problems...


HTH,
greetings
 
Nicholas Paldino said:
VMI,

The problem comes from using a character type. In .NET this is a
unicode character, and not an 8-bit ANSI character like it is in C. You can
declare the type two ways:

It's not very clear in sdk documenation but CharSet in
StructLayout/DllImport applies to char and char[] too, not only strings.

Greetings
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ZIP4_PARM
{
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string iadl1;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string ictyi;
public byte auto_zone_ind;
public byte retcc;
public footer foot;
public struct footer
{
public byte a;
public byte b;
public byte c;
public byte d;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
public string rsvd3;
}
}

The other way you can declare it is by declaring all of the character
fields as strings, and then tagging them so they are marshaled as
ByValTStrs, with a size of one. Either way should work.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

VMI said:
How can I convert the following C struct into a C# struct? The struct is
sent to an API function (written in C) as parameter, and the function fills
it with data. I tried to convert it and most of it works but the data in the
foot struct is not correct (I believe it's a conversion problem between C#
and C).
The class I created in C# (from the struct) is at the bottom.

typedef struct
{
char iadl1[50+1];
char ictyi[50+1];
char auto_zone_ind;
char retcc;
struct {
char a;
char b;
char c;
char d;
char rsvd3[6];
} foot;
} ZIP4_PARM;

*****************************
/* My struct converted */
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ZIP4_PARM
{
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string iadl1;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string ictyi;
public char auto_zone_ind;
public char retcc;
public footer foot;
public struct footer
{
public char a;
public char b;
public char c;
public char d;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
public string rsvd3;
}
}
 
Back
Top