How would I convert this struct?

A

Angel

How would I convert this struct into C#?

typedef struct
{
char rsvd0[4];
struct { //embedded struct
char a;
} foot;
ADDR_REC stack[10]; //This is the continuous problem
} ZIP4_PARM;


The ADDR_REC looks like this:
typedef struct
{
char detail_code;
char zip_code[5+1];
} ADDR_REC;

The original function call is:
int z4adrinq(ZIP4_PARM *parm);

The dll function is the only part of the application that accesses the
ADDR_REC stack. Since it's written in C, I assume it accesses it similar to
ZIP4_PARM.ADDR_REC[0].detail_code = 'xx'. I only need to convert the struct
so, when I send it to the function, it'll be able to write to it.

Angel

PS - A few years ago, when the USPS started working on a C# application that
interacts with the dll, they mentioned that, according to MS, C# didn't have
the capability to access an embedded record.
 
N

Nicholas Paldino [.NET/C# MVP]

Angel,

This is what I would use:

[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;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ZIP4_PARM
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=4)]
public string rsvd0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string foot_a;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public ADDR_REC[] stack;
}

Hope this helps.
 
A

Angel

I converted it like you suggested but I receive: " Can not marshal parameter
#1: Invalid managed/unmanaged type combination (this value type must be
paired with Struct)."

The function call is declared like this:

[DllImport("ZIP4_W32.DLL")]
public static extern int z4adrinq([In,
Out][MarshalAs(UnmanagedType.LPStruct)] ZIP4_PARM zip4_parm);

Thanks for you r help,
Angel


el,
This is what I would use:

[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;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ZIP4_PARM
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=4)]
public string rsvd0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string foot_a;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public ADDR_REC[] stack;
}

Hope this helps.


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


Angel said:
How would I convert this struct into C#?

typedef struct
{
char rsvd0[4];
struct { //embedded struct
char a;
} foot;
ADDR_REC stack[10]; //This is the continuous problem
} ZIP4_PARM;


The ADDR_REC looks like this:
typedef struct
{
char detail_code;
char zip_code[5+1];
} ADDR_REC;

The original function call is:
int z4adrinq(ZIP4_PARM *parm);

The dll function is the only part of the application that accesses the
ADDR_REC stack. Since it's written in C, I assume it accesses it
similar
to
ZIP4_PARM.ADDR_REC[0].detail_code = 'xx'. I only need to convert the struct
so, when I send it to the function, it'll be able to write to it.

Angel

PS - A few years ago, when the USPS started working on a C# application that
interacts with the dll, they mentioned that, according to MS, C# didn't have
the capability to access an embedded record.
 
N

Nicholas Paldino [.NET/C# MVP]

Angel,

Your declaration for the function should be:

[DllImport("ZIP4_W32.DLL")]
public static extern int z4adrinq(ref ZIP4_PARM zip4_parm);

And you need to call it with the ref keyword.


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

Angel said:
I converted it like you suggested but I receive: " Can not marshal parameter
#1: Invalid managed/unmanaged type combination (this value type must be
paired with Struct)."

The function call is declared like this:

[DllImport("ZIP4_W32.DLL")]
public static extern int z4adrinq([In,
Out][MarshalAs(UnmanagedType.LPStruct)] ZIP4_PARM zip4_parm);

Thanks for you r help,
Angel


el,
This is what I would use:

[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;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ZIP4_PARM
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=4)]
public string rsvd0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string foot_a;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public ADDR_REC[] stack;
}

Hope this helps.


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


Angel said:
How would I convert this struct into C#?

typedef struct
{
char rsvd0[4];
struct { //embedded struct
char a;
} foot;
ADDR_REC stack[10]; //This is the continuous problem
} ZIP4_PARM;


The ADDR_REC looks like this:
typedef struct
{
char detail_code;
char zip_code[5+1];
} ADDR_REC;

The original function call is:
int z4adrinq(ZIP4_PARM *parm);

The dll function is the only part of the application that accesses the
ADDR_REC stack. Since it's written in C, I assume it accesses it
similar
to
ZIP4_PARM.ADDR_REC[0].detail_code = 'xx'. I only need to convert the struct
so, when I send it to the function, it'll be able to write to it.

Angel

PS - A few years ago, when the USPS started working on a C#
application
that
interacts with the dll, they mentioned that, according to MS, C#
didn't
have
the capability to access an embedded record.
 
A

Angel

With the ref keyword, I still receive the error:
"Can not marshal parameter #1: Invalid managed/unmanaged type combination
(this value type must be paired with Struct)."

Angel


Nicholas Paldino said:
Angel,

Your declaration for the function should be:

[DllImport("ZIP4_W32.DLL")]
public static extern int z4adrinq(ref ZIP4_PARM zip4_parm);

And you need to call it with the ref keyword.


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

Angel said:
I converted it like you suggested but I receive: " Can not marshal parameter
#1: Invalid managed/unmanaged type combination (this value type must be
paired with Struct)."

The function call is declared like this:

[DllImport("ZIP4_W32.DLL")]
public static extern int z4adrinq([In,
Out][MarshalAs(UnmanagedType.LPStruct)] ZIP4_PARM zip4_parm);

Thanks for you r help,
Angel


el,
This is what I would use:

[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;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ZIP4_PARM
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=4)]
public string rsvd0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string foot_a;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public ADDR_REC[] stack;
}

Hope this helps.


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


How would I convert this struct into C#?

typedef struct
{
char rsvd0[4];
struct { //embedded struct
char a;
} foot;
ADDR_REC stack[10]; //This is the continuous problem
} ZIP4_PARM;


The ADDR_REC looks like this:
typedef struct
{
char detail_code;
char zip_code[5+1];
} ADDR_REC;

The original function call is:
int z4adrinq(ZIP4_PARM *parm);

The dll function is the only part of the application that accesses the
ADDR_REC stack. Since it's written in C, I assume it accesses it similar
to
ZIP4_PARM.ADDR_REC[0].detail_code = 'xx'. I only need to convert the
struct
so, when I send it to the function, it'll be able to write to it.

Angel

PS - A few years ago, when the USPS started working on a C# application
that
interacts with the dll, they mentioned that, according to MS, C# didn't
have
the capability to access an embedded record.
 
W

Willy Denoyette [MVP]

Please read the reply [1] I gave to your previous posting (Re: marshaling
problem with struct converted from C) , and don't start a new thread for the
same problem.

[1]
Yes, you should pass a pointer to a unmanaged buffer to the C function, on
return you should marshal the ADDR_REC array to an array of ADDR_REC
objects.

Following should get you a started.
Note: I changed the structs to classes because PtrToStructure needs an
object on the heap.

using System;
using System.Runtime.InteropServices;

class Tester
{
static void Main()
{
int arElements = 10;
ZIP4_PARM z = new ZIP4_PARM();
ADDR_REC ar = new ADDR_REC();
ADDR_REC[] arrrayar = new ADDR_REC[arElements];
int arBytes = Marshal.SizeOf(ar);
IntPtr ptrz = Marshal.AllocHGlobal( Marshal.SizeOf(z));
IntPtr ptra = Marshal.AllocHGlobal(arBytes);
int z4adrinq(ZIP4_PARM *parm);
Marshal.PtrToStructure(ptrz, z);
for (int i = 0; i < arElements; i++ )
{
int displ = i * arBytes;
Marshal.Copy(z.stack, displ , ptra, arBytes);
Marshal.PtrToStructure(ptra, ar);
arrrayar = ar;
}
Marshal.FreeHGlobal(ptrz);
Marshal.FreeHGlobal(ptra);
}
}
// struct changed into class !!!!!!
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ZIP4_PARM
{
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=51 )]
public string iadl2;
public short respn;
public char retcc;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=86 )]
public string rsvd2;
public footer foot;
public struct footer
{
public char a;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
public string rsvd3;
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst=90)]
public char[] stack;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class ADDR_REC
{
internal char detail_code;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6 )]
public string zip_code;
internal char action_code;
internal char sec_code;
}
}


Willy.
 

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