Проблема присвоения значений структуре в C ++ структуре, переданной из C # - PullRequest
2 голосов
/ 14 декабря 2009

У меня есть функция в C #, которая передает массив структур в DLL, написанную на C ++. Структура представляет собой группу целых чисел, и когда я считываю данные в DLL, все значения получаются в порядке. Однако, если я пытаюсь записать в элементы из C ++, значения никогда не отображаются, когда я пытаюсь читать, затем обратно в C #.

C #

[StructLayout(LayoutKind.Sequential)]
struct Box
{
  public int x;
  public int y;
  public int width;
  public int height;
}

[StructLayout(LayoutKind.Sequential)]
struct Spot
{
  public int x;
  public int y;
}

static void TestCvStructs()
{
  int len = 100;
  Box[] r = new Box[len];
  Spot[] p = new Spot[len];

  for (int i = 0; i < len; i++)
  {
    r[i].x = i*10;
    r[i].y = i * 200;
    r[i].width = r[i].x * 10;
    r[i].height = r[i].y * 100 + r[i].x * 5;

    p[i].x = i * 8;
    p[i].y = i * 12;
  }

  PassCvStructs(len, r, p);

  for (int i = 0; i < len; i++)
  {
    Console.WriteLine("Point/x:{0} Boxes/x{1}", p[i].x, r[i].x );
  }
}

[DllImport(dll)]
private static extern int PassSomeStructs(int count, Box[] boxes, Spot[] points);

C ++

typedef struct Box
{
  int x;
  int y;
  int width;
  int height;
} Box;

typedef struct Spot
{
  int x;
  int y;
} Spot;

CPPDLL_API int PassSomeStructs(int arrayLength, Box *boxes, Spot *points)
{
  for(int i = 0; i < arrayLength; ++i)
  {
    printf("Group:%i\n", i);
    printf("Rect - x:%i y:%i width:%i length:%i\n", boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height);
    printf("Point - x:%i y:%i\n", points[i].x, points[i].y);
    printf("\n");

    points[i].x = 3;
    boxes[i].x = 1;
  }
  return 0;
}

Ответы [ 3 ]

1 голос
/ 14 декабря 2009

Из статьи MDSN о маршалинге массивов: попробуйте установить следующий атрибут для типов вашего массива.Обычно это используется для вызова C # из C ++, но может также потребоваться для получения обновленных значений обратно в C #.

[DllImport(dll)]
private static extern int PassSomeStructs(int count, 
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Box[] boxes, 
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Spot[] points);

Также см. Эту статью для примера успешного двустороннего маршаллинга:

http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/ff0123d0-506b-4de2-bfb5-f690c9358826/

0 голосов
/ 15 декабря 2009

Я нашел ответ на другой вопрос: Как упорядочить массив структур в C #?

При маршалинге, по-видимому, по умолчанию маршалируются параметры как In. В противном случае они должны быть явно объявлены как Out или In, Out. После указания, что явно мой код, пример теперь работает.

Благодаря его Skeetness за ответ и antonmarkov за разоблачение MarshalAs.

private static extern int PassSomeStructs(int count, [In, Out] Box[] boxes, [In, Out] Spot[] points);
0 голосов
/ 14 декабря 2009

Вы пытались добавить ключевое слово ref / out в свой C # extern?

Другая идея состоит в том, чтобы попытаться передать IntPtr вместо самого класса или передать его как -IntPtr ...

Я считаю, что структуры копируются, а по умолчанию не передаются по ссылке.

Честно нанести удар в темноте, но у вас пока нет ответов, так что, надеюсь, это поможет ...

Interop все еще находится на стадии "это волшебство" для меня ...

...