简体   繁体   中英

Returning an array of structs with struct containing char[] with PInvoke

I have a array of structs returned from PInvoke, and it returns the array fine if the struct just contains int or float, but when i try to return an array of char it starts to get messy, i have tried with returning an IntPtr, but that has not been successfull. Any ideas how i can get this working?

C code

struct  return_part {
    int partid;
    int numcomp;
    int parttype;
    char partname[100];
};

extern int return_parts(return_part ** array, int * arraySizeInElements) {
    int partcount = 0;
    struct list_part *currentnode; 
    currentnode = head;
    struct section_list *section;
    struct return_part *temppart;

    while (currentnode != NULL) {
        partcount++;
        currentnode = currentnode->next;
    }

    currentnode = head;
    *arraySizeInElements = partcount;

    int bytesToAlloc = sizeof(return_part) * (*arraySizeInElements);
    return_part * a = static_cast<return_part *>(CoTaskMemAlloc(bytesToAlloc));
    *array = a;

    int q = 0;
    while (currentnode != NULL) {
        struct return_part tmp;
        tmp.partid = currentnode->partid;
        tmp.numcomp = currentnode->numcomp;
        strcpy(tmp.partname, currentnode->partname);
        tmp.parttype = currentnode->parttype;

        a[q] = tmp;
        q++;
        currentnode = currentnode->next;
    }

    return 0;
}

C# Code

[StructLayout(LayoutKind.Sequential)]
public struct return_part {
    public int partid;
    public int numcomp;
    public int parttype;
    public char partname;
};

internal static class UnsafeNativeMethods
{
    [DllImport(_dllLocation, CallingConvention = CallingConvention.Cdecl)]
    public static extern int return_parts([MarshalAs(UnmanagedType.LPArray,
    SizeParamIndex = 1)] out return_part[] array, out int arraySizeInElements);
}

public static ReturnPoint[] getpoints(int partid) {
    return_parts[] parts;
    int size;
    int result = UnsafeNativeMethods.return_parts(out parts, out size)
}

An array of characters, to unmanaged code, is just a string, so you have two options here. Which one you use depends on how you actually need to use the character data when it's back in C#-land:

  1. Marshal it as an array. See this article for how arrays embedded into structures get marshalled (EDIT: this needs to be ByValArray, not LPArray as I originally indicated; Thanks @Hans):

     [StructLayout(LayoutKind.Sequential)] public struct return_part { public int partid; public int numcomp; public int parttype; [MarshalAs(UnmanagedType.ByValArray, SizeConst=100)] public char[] partname; }; 
  2. Marshal it as a string. See this article for how to marshal strings contained within structures.

     [StructLayout(LayoutKind.Sequential)] public struct return_part { public int partid; public int numcomp; public int parttype; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=100)] public string partname; }; 

On the C# side, your structure has a single character as partname. Try using either:

char[] partname; //-- A character array

byte[] partname; //-- A byte array

string partname; //-- A string

I'd tend to prefer the string if that works. The byte might work because byte in C# lines up more logically with char in C. The character array might also work because the character in C# logically represents an actual single character (intended use), something C doesn't really have (short of unsigned integer types).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM