Передача массива целых из C # в нативный код с помощью взаимодействия - PullRequest
3 голосов
/ 25 мая 2011

У меня есть Blah.cs:

public unsafe static int Main()
{
  int[] ai = {1, 2, 3, 4, 5};
  UIntPtr stai = (UIntPtr) ai.Length;
  CManagedStuff obj = new CManagedStuff();
  obj.DoSomething(ai, stai);
}

Тогда ManagedStuff.cpp:

void CManagedStuff::DoSomething(int^ _ai, UIntPtr _stai)
{
  // Here I should do something to marshal the int^ to an int*
  pUnmanagedStuff->DoSomething(_ai, (size_t) _stai);
}

И UnmanagedStuff.cpp:

void CUnmanagedStuff::DoSomething(int* _ai, size_t _stai)
{
  // Walk and print the _stai ints in _ai
}

Как я могу передать int[] ai из Main в ManagedStuff :: DoSomething? Я понимаю, что в этом вызове нет маршалинга, потому что весь код управляется.

А как мне тогда маршала int^ _ai в ManagedStuff :: DoSomething для вызова UnmanagedStuff :: DoSomething? Если бы у меня был int[] _ai, то код в ответе на этот вопрос SO может помочь ( C #: выделение «указателя на массив int» из SendMessage () lParam ).

В качестве альтернативы, как мне избежать работы с C #, взаимодействием C ++, Microsoft и Windows и остановить страдания мира?

Ответы [ 3 ]

2 голосов
/ 26 мая 2011

Мне просто нужно указать, насколько нарушена оригинальная идея.

В нативном коде вы можете передавать массив, передавая адрес первого элемента, поскольку соседние элементы можно найти с помощью арифметики указателей.

В управляемом коде элементы также хранятся рядом, но int^ пропускает элемент, делая копию вне массива. Эта копия не будет содержать никаких других элементов массива поблизости.

Фактически, это также происходит в нативных межпроцессных обменах данными. Хитрость в использовании арифметики указателей для поиска других элементов работает только в процессе и обычно не применяется.

1 голос
/ 25 мая 2011

ОК, у меня это работает так:

void CManagedStuff::DoSomething(array<int>^ _ai, UIntPtr _stai)
{
  // Here I should do something to marshal the int^ to an int*
  pin_ptr<int> _aiPinned = &_ai[0];
  pUnmanagedStuff->DoSomething(_aiPinned, (size_t) _stai);
}

Во-первых, передавая array<int>^.
Во-вторых, как предлагал Тамши, используя указатель булавки, указывающий на адреспервый элемент в массиве.

1 голос
/ 25 мая 2011

Вы должны закрепить управляемый ресурс (ваш массив), чтобы сборщик мусора не перемещал его, пока вы используете указатель.

В C # вы можете сделать это с помощью оператора fixed: фиксированный оператор (C # Reference)

Закрепление в C ++ работает с указателями закрепления, которые прикрепляют управляемый объект, пока они находятся в области видимости. (Указатель на любой элемент закрепит весь массив):

// In CManagedStuff:
pin_ptr<int> _aiPinned = _ai

Подробнее: C ++ / CLI в действии - Использование внутренних и закрепляющих указателей

...