Обертывание нативной функции C ++ с несколькими выходами в .dll для использования в C # - PullRequest
2 голосов
/ 13 июля 2011

Я обертываю некоторый нативный код C ++ в C ++ / CLI .dll для использования в проектах .NET - в основном, на C #. Количество звонков будет большим, поэтому я собираюсь сделать это эффективно. Обертываемая мной функция принимает следующие аргументы:

int SomeFun(
       const char* input_text,
       int* output_array,
       bool* output_value);

Я знаю, как сделать эффективное System::String на const char* приведение благодаря этому ответу . У меня такие вопросы:

  1. Функция ожидает указатели на output_array и output_value, которые необходимо создать / очистить и вернуть управляемому компоненту внутри оболочки. Как мне это сделать?
  2. Как вернуть несколько значений в управляемую среду из оболочки .dll - используя struct в качестве возвращаемого значения?
  3. На данный момент я пытаюсь выполнить всю обработку указателей и управляемое / неуправляемое взаимодействие внутри оболочки .dll, но эта статья (Решение 3) предполагает, что использование "небезопасной" среды внутри C # является самым быстрым , Может ли это быть лучшим вариантом для того, что я пытаюсь сделать? Я предполагаю, что это сделает обертку менее сложной, но также потребует более сложной обработки в C #.

Спасибо

/ David

1 Ответ

1 голос
/ 13 июля 2011

Вы можете закрепить массивы так же, как вы прикрепляете строки, например, для байта []:

pin_ptr<Byte> ptrBytes = &myArray[myArray->GetLowerBound(0)];

ptrBytes теперь можно использовать как символ без знака *

Вы можете закрепить отдельные переменныетоже из C #, например, с параметром, который ссылается на int и называется int% ival:

pin_ptr<int> pInt =   &ival;

pInt теперь можно использовать как int *

Вы можетесоздайте массивы с помощью gcnew, например, чтобы создать массив байтов для возврата в C #:

array<Byte>^ streambuf = gcnew array<Byte>(bufSize+16);

Теперь вы можете заполнить его streambuf [index], переупаковывая массив C ++ в цикле, или вы можете закрепитьэто и сделать memcpy, прежде чем вернуть его в C #.

Я обычно не возвращаю структуры.Я обычно определяю каждый параметр в оболочке функции C ++ / CLI.Например, если бы структура имела два целых числа и строку, я бы сделал каждый параметр параметром с ключевым словом ref (% в C ++ / CLI, например, int% ival).если вам нужно вернуть большое количество значений, проще всего вернуть класс, созданный с помощью gcnew, а не struct.

Использование небезопасного кода - это то, что нужно, если вы пытаетесь ускорить доступ к массиву и ваш C #код будет простым.Если у вас уже есть код C ++, и он использует STL, и он очень сложный, и вы не хотите его переписывать, особенно если у вас много арифметики и приведения указателей, придерживайтесь оболочки C ++ / CLI.

...