Question

I am running into an issue where data from the parent struct is correctly marshalled, but the data in the child struct is not. The struct definitions and functions in C:

struct contact_info {
    char cell[32];
    char home[32];
};

struct human {
    char first[32];
    char last[32];
    struct contact_info *contact;
};

__declspec(dllexport) int __cdecl say_hello(struct human *person);
__declspec(dllexport) int __cdecl import_csv(char *csvPath, struct human *person);

The C# P/Invoke code:

[StructLayout(LayoutKind.Sequential)]
public struct contact_info
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public String cell;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public String home;
}

[StructLayout(LayoutKind.Sequential)]
public struct human
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public String first;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public String last;
    public IntPtr contact;
}

[DllImport("HelloLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int say_hello(ref human person);

[DllImport("HelloLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int import_csv([MarshalAs(UnmanagedType.LPStr)]String path, ref human person);

When I put the code to use:

HelloLibrary.human human = new HelloLibrary.human();
human.contact = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HelloLibrary.contact_info)));
HelloLibrary.contact_info contact = (HelloLibrary.contact_info)
    Marshal.PtrToStructure(human.contact, typeof(HelloLibrary.contact_info));

HelloLibrary.import_csv(args[0], ref human);

Console.WriteLine("first:'{0}'", human.first);
Console.WriteLine("last:'{0}'", human.last);
Console.WriteLine("cell:'{0}'", contact.cell);
Console.WriteLine("home:'{0}'", contact.home);

The human.first and human.last are marshalled correctly (e.g. "Joe" and "Schmoe"), however the contact.cell and contact.home are not. The contact.cell is usually some garbage and contact.home is nothing.

I am still pretty new to marshalling. Am I not marshalling correctly? Why is the struct contact_info *contact data not being set correctly?

For full source see this GitHub gist.

Was it helpful?

Solution

Your are converting human.contact to your structure before calling import_csv, so it will contain anything left in memory when you did allocate it.

If you move the line where you create contact below your call to import_csv it should have the right data.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top