Converting C-struct (with array) to C#

V

VMI

How can I convert this struct into a C# struct? The problem with this one is
that one of its members is an array of ADDR_REC(another struct), and the API
function (written in C) writes to this part of the struct. I call the
function with struct CITY_REC as parameter and the API function writes to
this stack. Any help is appreciated. I've converted ADDR_REC to C# but I
have no idea what to do with CITY_REC.

typedef struct
{
char mpnum[10+1];
ADDR_REC stack[10];
} CITY_REC;

typedef struct
{
char detail_code;
char zip_code[5+1];
char update_key[10+1];
} ADDR_REC;
 
N

Nicholas Paldino [.NET/C# MVP]

VMI,

It's easy, you would decare it like this:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ADDR_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string detail_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string zip_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string update_key;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct CITY_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string mpnum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public ADDR_REC[] stack;
}

Hope this helps.
 
N

Niki Estner

I've run across the same problem, I don't think there is a direct solution
to it: MS simply hasn't implemented this kind of marshaling.

This has already been discussed at: http://tinyurl.com/3lswk. A workaround
is mentioned there, too.

Sorry

Niki
 
V

VMI

We had already tried it like this. But when we run the application, we get
this exception:

"Additional information: Can not marshal field stack of type
Structs.CITY_REC: This type can not be marshaled as a structure field."

This is how we did it (more or less like your suggestion). I hadn't posted
the CITY_REC footer because I assumed that it was not causing this error
(and I wanted to make the post short).

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ADDR_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string detail_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string zip_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string update_key;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class CITY_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string mpnum;
public footer foot;
public struct footer
{
public byte a;
public byte b;
public byte c;
public byte d;
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public ADDR_REC[] stack;
}










Nicholas Paldino said:
VMI,

It's easy, you would decare it like this:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ADDR_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string detail_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string zip_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string update_key;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct CITY_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string mpnum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public ADDR_REC[] stack;
}

Hope this helps.


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


VMI said:
How can I convert this struct into a C# struct? The problem with this
one
is
that one of its members is an array of ADDR_REC(another struct), and the API
function (written in C) writes to this part of the struct. I call the
function with struct CITY_REC as parameter and the API function writes to
this stack. Any help is appreciated. I've converted ADDR_REC to C# but I
have no idea what to do with CITY_REC.

typedef struct
{
char mpnum[10+1];
ADDR_REC stack[10];
} CITY_REC;

typedef struct
{
char detail_code;
char zip_code[5+1];
char update_key[10+1];
} ADDR_REC;
 
N

Niki Estner

Hopefully MS will implement this in the next version of the framework. It
doesn't work on any of the current versions. UnmanagedType.ByValArray can
only be used for arrays simple types.

Try yourself: pass the CITY_REC type you described to Marshal.SizeOf. Change
the array type from ADDR_REC[] to byte[], int[] or some other simple type,
and it will work.

Niki

Nicholas Paldino said:
VMI,

It's easy, you would decare it like this:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ADDR_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string detail_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string zip_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string update_key;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct CITY_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string mpnum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public ADDR_REC[] stack;
}

Hope this helps.


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


VMI said:
How can I convert this struct into a C# struct? The problem with this
one
is
that one of its members is an array of ADDR_REC(another struct), and the API
function (written in C) writes to this part of the struct. I call the
function with struct CITY_REC as parameter and the API function writes to
this stack. Any help is appreciated. I've converted ADDR_REC to C# but I
have no idea what to do with CITY_REC.

typedef struct
{
char mpnum[10+1];
ADDR_REC stack[10];
} CITY_REC;

typedef struct
{
char detail_code;
char zip_code[5+1];
char update_key[10+1];
} ADDR_REC;
 
V

VMI

Were you able to resolve the problem with the workaround in the link you
posted (http://tinyurl.com/3lswk) ?

Niki Estner said:
Hopefully MS will implement this in the next version of the framework. It
doesn't work on any of the current versions. UnmanagedType.ByValArray can
only be used for arrays simple types.

Try yourself: pass the CITY_REC type you described to Marshal.SizeOf. Change
the array type from ADDR_REC[] to byte[], int[] or some other simple type,
and it will work.

Niki

VMI,

It's easy, you would decare it like this:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ADDR_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string detail_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string zip_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string update_key;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct CITY_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string mpnum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public ADDR_REC[] stack;
}

Hope this helps.


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


VMI said:
How can I convert this struct into a C# struct? The problem with this
one
is
that one of its members is an array of ADDR_REC(another struct), and
the
API
function (written in C) writes to this part of the struct. I call the
function with struct CITY_REC as parameter and the API function writes to
this stack. Any help is appreciated. I've converted ADDR_REC to C# but I
have no idea what to do with CITY_REC.

typedef struct
{
char mpnum[10+1];
ADDR_REC stack[10];
} CITY_REC;

typedef struct
{
char detail_code;
char zip_code[5+1];
char update_key[10+1];
} ADDR_REC;
 
N

Niki Estner

The basic idea of the workaround is to create a struct that contains a
private byte array, and public indexer methods so you can use it like an
array from outside. The byte array can be marshaled using
UnmanagedType.ByValArray, and the indexer methods may use unsafe code or
functions in the Marshal class to perform their task.
So, yes it works, but it's only beautiful on the outside...

Niki

VMI said:
Were you able to resolve the problem with the workaround in the link you
posted (http://tinyurl.com/3lswk) ?

Niki Estner said:
Hopefully MS will implement this in the next version of the framework. It
doesn't work on any of the current versions. UnmanagedType.ByValArray can
only be used for arrays simple types.

Try yourself: pass the CITY_REC type you described to Marshal.SizeOf. Change
the array type from ADDR_REC[] to byte[], int[] or some other simple type,
and it will work.

Niki

VMI,

It's easy, you would decare it like this:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ADDR_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string detail_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string zip_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string update_key;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct CITY_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string mpnum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public ADDR_REC[] stack;
}

Hope this helps.


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


How can I convert this struct into a C# struct? The problem with
this
one
is
that one of its members is an array of ADDR_REC(another struct), and the
API
function (written in C) writes to this part of the struct. I call the
function with struct CITY_REC as parameter and the API function
writes
to
this stack. Any help is appreciated. I've converted ADDR_REC to C#
but
I
have no idea what to do with CITY_REC.

typedef struct
{
char mpnum[10+1];
ADDR_REC stack[10];
} CITY_REC;

typedef struct
{
char detail_code;
char zip_code[5+1];
char update_key[10+1];
} ADDR_REC;
 

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