Возврат массива структур со структурой, содержащей char[] с помощью PInvoke

У меня есть массив структур, возвращаемый из PInvoke, и он возвращает массив в порядке, если структура просто содержит int или float, но когда я пытаюсь вернуть массив char, он начинает запутываться, я пытался вернуть IntPtr, но это не увенчалось успехом. Любые идеи, как я могу заставить это работать?

C-код

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

Код С#

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

person user978281    schedule 06.01.2012    source источник


Ответы (2)


Массив символов для неуправляемого кода — это просто строка, поэтому здесь у вас есть два варианта. Какой из них вы используете, зависит от того, как вам на самом деле нужно использовать символьные данные, когда они вернутся в С#-страну:

  1. Упорядочите его как массив. См. эту статью о внедрении массивов в структуры маршалируются (EDIT: это должен быть ByValArray, а не LPArray, как я изначально указал; спасибо @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. Упорядочите его как строку. См. эту статью, как маршалировать строки, содержащиеся в структурах.

    [StructLayout(LayoutKind.Sequential)]
    public struct return_part {
      public int partid;
      public int numcomp;
      public int parttype;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=100)]
      public string partname;
    };
    
person Michael Edenfield    schedule 06.01.2012
comment
LPArray неверен, это превращает его в char*, а не в char[]. Второй фрагмент хорош. - person Hans Passant; 06.01.2012
comment
Моя ошибка, ты прав; эквивалентность массива/указателя истинна только в параметрах функции, а не встроена в структуры. Редактирование, чтобы исправить это. - person Michael Edenfield; 07.01.2012

На стороне C# ваша структура имеет один символ в качестве имени детали. Попробуйте использовать либо:

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

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

string partname; //-- A string

Я бы предпочел строку, если это работает. Байт может работать, потому что byte в C# более логично выстраивается в линию с char в C. Массив символов также может работать, потому что символ в C# логически представляет фактический одиночный символ (использование по назначению), чего на самом деле нет в C (за исключением беззнакового символа). целочисленные типы).

person Sheridan Bulger    schedule 06.01.2012