2012-08-15 2 views
4

Я пытаюсь использовать pinvoke для сортировки массива структур внутри другой структуры от C до C#. AFAIK, нет.
Итак, в структуре C я объявляю ptr для своего массива и malloc. Проблемы: 1) Как объявить эквивалент на стороне C#? 2) Как распределить и использовать эквивалент на стороне C#?Как использовать pinvoke для C struct array указатель на C#

//The C code 
typedef struct { 
     int a; 
     int b; } A; 
typedef struct { 
     int c; 
     // A myStruct[100]; // can't do this, so: 
     A *myStruct; } B; 

//The c# code: 
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public class A{ 
    int a; 
    int b; 
} 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public class B{ 
     int c; 
     // can't declare array of [100] A structures... 
    ? 
} 

[EDIT]: Как-то я неправильно то, что я прочитал в другом месте о фиксированном массиве объектов на C# стороне. И я может зафиксировать размер массива в C Так компилируется нормально, но затем я получаю «ссылка на объект не указывает на экземпляр объекта» при использовании:

data.B[3].a = 4567; Так, чтение в другом месте о том, что может быть эта ошибка , Я добавил этот метод:

public void initA() 
     { 
      for (int i = 0; i < 100; i++) { B[i] = new A(); } 
     } 

Снова скомпилировано ОК, но с той же ошибкой.

+0

Вы пробовали 'A [] myStruct'? –

+0

Это компилируется нормально. Но как я могу выделить хранилище и использовать его (я все еще изучаю C#). Благодарю. – PaeneInsula

+0

просто любопытно: * почему * вы не можете использовать 'A myStruct [100];' in C? Это сделало бы намного проще на стороне C# ... –

ответ

5

Чтобы создать «сложные» структуры, подобные этому между C и C#, у вас есть несколько вариантов.

В этом случае я настоятельно рекомендую вам встроить фиксированный массив в структуру C-стороны, так как это упростит сторону C#. Вы можете использовать атрибут MarshalAs сказать C# сколько места необходимо выделить в массиве во время выполнения:

// In C: 
typedef struct 
{ 
int a; 
int b; 
} A; 

typedef struct 
{ 
int c; 
A data[100]; 
} B; 

// In C#: 
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct A 
{ 
    int a; 
    int b; 
} 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct B 
{ 
    int c; 
    [MarshalAs(UnmanagedType.LPArray, SizeConst=100)] 
    A[] data = new data[100]; 
} 

Если вы не знаете, или не может указать, фиксированный размер для вашего массива , тогда вам нужно будет сделать то, что вы сделали, и объявить его как указатель на C. В этом случае вы не можете указать C#, сколько памяти будет использовать массив во время выполнения, поэтому вы в значительной степени застреваете с выполняя все рулевое управление вручную. This question имеет хорошее краткое изложение того, как это работает, но основная идея:

  1. Вы должны добавить поле в вашу структуру, которая включает в себя количество элементов массива (это сделает вашу жизнь намного проще)
  2. Объявите поле в C# как: IntPtr data; без атрибутов.
  3. Используйте Marshal.SizeOf(typeof(A)), чтобы получить размер структуры в неуправляемой памяти.
  4. Использование Marshal.PtrToStructure для преобразования одного неуправляемого структуру C#
  5. Использование IntPtr.Add(ptr, sizeofA) для перехода к следующей структуры в массиве
  6. Loop, пока не закончатся.
+0

ссылка на объект не установлена ​​в экземпляр объекта objec – PaeneInsula

+0

См. Мое редактирование выше о том, как я пытался исправить сообщение об ошибке. – PaeneInsula

+0

На размер C# вам все равно нужно назначить массив полю, так как массивы являются ссылочными типами. Вы должны иметь возможность сделать это inline, я отредактировал свой ответ. –

Смежные вопросы