hrlp with custom marshaling of struct

V

Vaughn

What code would I need to write to this struct? The following code
deserializes the struct so the function runs correctly. But in order to
write to the struct before doing the function call, I need to add code in
System.IntPtr ICustomMarshaler.MarshalManagedToNative(object ManagedObj) and
void ICustomMarshaler.CleanUpNativeData(System.IntPtr pNativeData)

Any help would really be appreciated.

Zip4Parm zip4parm;
Zip4Parm.z4adrinq(out zip4parm); // DLL function call
//now use zip4parm here

public class Zip4Parm {
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
private struct ZIP4_PARM {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=4)]
public string rsvd0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=26)]
public string footer;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ADDR_REC {
public byte detail_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string zip_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string update_key;
public byte action_code;
public byte rec_type;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=5)]
public string carr_rt;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=3)]
public string pre_dir;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=29)]
public string str_name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=5)]
public string suffix;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=3)]
public string post_dir;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string prim_low;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string prim_high;
public byte prim_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
public string sec_name;
}

private class Zip4ParmMarshaler: ICustomMarshaler {
private int arrayLength;

private Zip4ParmMarshaler(int arrayLength) {
this.arrayLength=arrayLength;
}

object ICustomMarshaler.MarshalNativeToManaged(System.IntPtr
pNativeData) {
ZIP4_PARM
zip4_parm=(ZIP4_PARM)Marshal.PtrToStructure(pNativeData, typeof(ZIP4_PARM));
pNativeData=new
IntPtr(pNativeData.ToInt32()+Marshal.SizeOf(typeof(ZIP4_PARM)));
ADDR_REC[] stack=new ADDR_REC[arrayLength];
for (int i=0; i<arrayLength; i++) {

stack=(ADDR_REC)Marshal.PtrToStructure(pNativeData, typeof(ADDR_REC));
pNativeData=new
IntPtr(pNativeData.ToInt32()+Marshal.SizeOf(typeof(ADDR_REC)));
}
return new Zip4Parm(zip4_parm, stack);
}

int ICustomMarshaler.GetNativeDataSize() {
return
Marshal.SizeOf(typeof(ZIP4_PARM))+Marshal.SizeOf(typeof(ADDR_REC))*arrayLeng
th;
}

System.IntPtr ICustomMarshaler.MarshalManagedToNative(object
ManagedObj) {
throw new NotImplementedException();
}

void ICustomMarshaler.CleanUpManagedData(object ManagedObj)
{}

void ICustomMarshaler.CleanUpNativeData(System.IntPtr
pNativeData) {}

public static ICustomMarshaler GetInstance(string cookie) {
return new Zip4ParmMarshaler(cookie=="" ? 10 :
int.Parse(cookie));
}
}

[DllImport("ZIP4_W32.DLL")]
public static extern int
z4adrinq([Out][MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef=typeof(Zip4ParmMarshaler))] out Zip4Parm zip4_parm);

public readonly string rsvd0;
public readonly string footer;
public readonly ADDR_REC[] stack;

private Zip4Parm(ZIP4_PARM zip4_parm, ADDR_REC[] stack) {
rsvd0=zip4_parm.rsvd0;
footer=zip4_parm.footer;
this.stack=stack;
}
}
 
N

Nicholas Paldino [.NET/C# MVP]

Vaughn,

I remember you posting before on this topic. Can you give the original
structure definitions again?


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

Vaughn said:
What code would I need to write to this struct? The following code
deserializes the struct so the function runs correctly. But in order to
write to the struct before doing the function call, I need to add code in
System.IntPtr ICustomMarshaler.MarshalManagedToNative(object ManagedObj) and
void ICustomMarshaler.CleanUpNativeData(System.IntPtr pNativeData)

Any help would really be appreciated.

Zip4Parm zip4parm;
Zip4Parm.z4adrinq(out zip4parm); // DLL function call
//now use zip4parm here

public class Zip4Parm {
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
private struct ZIP4_PARM {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=4)]
public string rsvd0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=26)]
public string footer;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ADDR_REC {
public byte detail_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string zip_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string update_key;
public byte action_code;
public byte rec_type;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=5)]
public string carr_rt;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=3)]
public string pre_dir;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=29)]
public string str_name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=5)]
public string suffix;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=3)]
public string post_dir;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string prim_low;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string prim_high;
public byte prim_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
public string sec_name;
}

private class Zip4ParmMarshaler: ICustomMarshaler {
private int arrayLength;

private Zip4ParmMarshaler(int arrayLength) {
this.arrayLength=arrayLength;
}

object ICustomMarshaler.MarshalNativeToManaged(System.IntPtr
pNativeData) {
ZIP4_PARM
zip4_parm=(ZIP4_PARM)Marshal.PtrToStructure(pNativeData, typeof(ZIP4_PARM));
pNativeData=new
IntPtr(pNativeData.ToInt32()+Marshal.SizeOf(typeof(ZIP4_PARM)));
ADDR_REC[] stack=new ADDR_REC[arrayLength];
for (int i=0; i<arrayLength; i++) {

stack=(ADDR_REC)Marshal.PtrToStructure(pNativeData, typeof(ADDR_REC));
pNativeData=new
IntPtr(pNativeData.ToInt32()+Marshal.SizeOf(typeof(ADDR_REC)));
}
return new Zip4Parm(zip4_parm, stack);
}

int ICustomMarshaler.GetNativeDataSize() {
return
Marshal.SizeOf(typeof(ZIP4_PARM))+Marshal.SizeOf(typeof(ADDR_REC))*arrayLeng
th;
}

System.IntPtr
ICustomMarshaler.MarshalManagedToNative(object
ManagedObj) {
throw new NotImplementedException();
}

void ICustomMarshaler.CleanUpManagedData(object ManagedObj)
{}

void ICustomMarshaler.CleanUpNativeData(System.IntPtr
pNativeData) {}

public static ICustomMarshaler GetInstance(string cookie) {
return new Zip4ParmMarshaler(cookie=="" ? 10 :
int.Parse(cookie));
}
}

[DllImport("ZIP4_W32.DLL")]
public static extern int
z4adrinq([Out][MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef=typeof(Zip4ParmMarshaler))] out Zip4Parm zip4_parm);

public readonly string rsvd0;
public readonly string footer;
public readonly ADDR_REC[] stack;

private Zip4Parm(ZIP4_PARM zip4_parm, ADDR_REC[] stack) {
rsvd0=zip4_parm.rsvd0;
footer=zip4_parm.footer;
this.stack=stack;
}
}
 
V

Vaughn

The original function call looks like this:
int z4adrinq(ZIP4_PARM *parm);

Original structure:
typedef struct
{
char rsvd0[4];
struct {
char a;
} foot;
ADDR_REC stack[10]; //PROBLEM
} ZIP4_PARM;

typedef struct
{
char detail_code;
char zip_code;
} ADDR_REC;

You sent an email to Angel (who's working with me on this) saying that it
should be converted to the following but, during the function call I'd get
this error"can not marshal field stack of type ZM7.ZIP4_PARM: This type can
not be marshaled as a structure field". This is the code we tried:
:
[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;
}

Thanks.

Nicholas Paldino said:
Vaughn,

I remember you posting before on this topic. Can you give the original
structure definitions again?


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

Vaughn said:
What code would I need to write to this struct? The following code
deserializes the struct so the function runs correctly. But in order to
write to the struct before doing the function call, I need to add code in
System.IntPtr ICustomMarshaler.MarshalManagedToNative(object ManagedObj) and
void ICustomMarshaler.CleanUpNativeData(System.IntPtr pNativeData)

Any help would really be appreciated.

Zip4Parm zip4parm;
Zip4Parm.z4adrinq(out zip4parm); // DLL function call
//now use zip4parm here

public class Zip4Parm {
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
private struct ZIP4_PARM {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=4)]
public string rsvd0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=26)]
public string footer;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ADDR_REC {
public byte detail_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string zip_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string update_key;
public byte action_code;
public byte rec_type;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=5)]
public string carr_rt;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=3)]
public string pre_dir;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=29)]
public string str_name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=5)]
public string suffix;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=3)]
public string post_dir;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string prim_low;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string prim_high;
public byte prim_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
public string sec_name;
}

private class Zip4ParmMarshaler: ICustomMarshaler {
private int arrayLength;

private Zip4ParmMarshaler(int arrayLength) {
this.arrayLength=arrayLength;
}

object ICustomMarshaler.MarshalNativeToManaged(System.IntPtr
pNativeData) {
ZIP4_PARM
zip4_parm=(ZIP4_PARM)Marshal.PtrToStructure(pNativeData, typeof(ZIP4_PARM));
pNativeData=new
IntPtr(pNativeData.ToInt32()+Marshal.SizeOf(typeof(ZIP4_PARM)));
ADDR_REC[] stack=new ADDR_REC[arrayLength];
for (int i=0; i<arrayLength; i++) {

stack=(ADDR_REC)Marshal.PtrToStructure(pNativeData, typeof(ADDR_REC));
pNativeData=new
IntPtr(pNativeData.ToInt32()+Marshal.SizeOf(typeof(ADDR_REC)));
}
return new Zip4Parm(zip4_parm, stack);
}

int ICustomMarshaler.GetNativeDataSize() {
return

Marshal.SizeOf(typeof(ZIP4_PARM))+Marshal.SizeOf(typeof(ADDR_REC))*arrayLeng
th;
}

System.IntPtr
ICustomMarshaler.MarshalManagedToNative(object
ManagedObj) {
throw new NotImplementedException();
}

void ICustomMarshaler.CleanUpManagedData(object ManagedObj)
{}

void ICustomMarshaler.CleanUpNativeData(System.IntPtr
pNativeData) {}

public static ICustomMarshaler GetInstance(string cookie) {
return new Zip4ParmMarshaler(cookie=="" ? 10 :
int.Parse(cookie));
}
}

[DllImport("ZIP4_W32.DLL")]
public static extern int
z4adrinq([Out][MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef=typeof(Zip4ParmMarshaler))] out Zip4Parm zip4_parm);

public readonly string rsvd0;
public readonly string footer;
public readonly ADDR_REC[] stack;

private Zip4Parm(ZIP4_PARM zip4_parm, ADDR_REC[] stack) {
rsvd0=zip4_parm.rsvd0;
footer=zip4_parm.footer;
this.stack=stack;
}
}
 

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