Получение неуправляемых функций C ++ из C # - PullRequest
4 голосов
/ 03 марта 2009

У меня есть некоторый стандартный код C ANSI, который является авторитетным. Это означает, что, хотя у меня есть источник, я не могу ни переводить на другой язык, ни изменять вызывающие аргументы, так как эти действия аннулируют полномочия. Есть более 150 функций.

Я могу внести непредвиденные изменения, например изменить имена файлов с .C на .CPP, чтобы он компилировался с использованием компилятора C ++ Visual Studio 2009, что я и сделал. Директивы компилятора и тому подобное также могут быть добавлены. Я также могу пройти слой обертки, если это необходимо.

Еще одно ограничение - моя компания не хочет, чтобы я использовал ключевое слово небезопасное в любом коде C #.

Мне нужно получить эти функции из программы на C #.

Типичная функция C / C ++ выглядит следующим образом:
double SomeFunction(double a, double[3] vec, double[3][3] mat);
Где содержимое массива иногда вводится, иногда выводится, а редко и то и другое.

Сначала я попытался создать неуправляемую DLL (с ​​функциями, помеченными как Extern C). Функции с только простыми аргументами (int, double) работали нормально, но я не мог определить, как маршалировать массивы. (На самом деле, я нашел некоторый пример кода, но это было чрезвычайно сложно и неразумно дублировать 150 раз.)

Затем я попробовал два проекта в одном решении, один на C ++, а другой на C #. В проекте C ++ я создал управляемую функцию, которая просто вызывала исходную функцию, которая была помечена как неуправляемая. Это было очень чисто и просто, и опять же, простые аргументы работали нормально. Но для массивов я не смог найти, как сделать так, чтобы типы аргументов соответствовали границам C # и C ++:
<i> Argument '2': cannot convert from 'double[]' to 'double*'</i>
(и как уже упоминалось выше, я не могу использовать небезопасный, чтобы получить указатель).

Конечно, то, что я пытаюсь сделать, должно быть возможным.
Каков наилучший способ получить эти функции?
(Пример кода с использованием вышеуказанной функции был бы действительно крут.)

Ответы [ 3 ]

4 голосов
/ 03 марта 2009

Пример реализации C / C ++:

extern "C" __declspec(dllexport)
double SomeFunction(double a, double vec[3], double mat[3][3]) {
  double sum = a;
  for (int ix = 0; ix < 3; ++ix) {
    sum += vec[ix];
    for (int iy = 0; iy < 3; ++iy) {
      sum += mat[ix][iy];
    }
  }
  return sum;
}

Пример использования C #:

private void Form1_Load(object sender, EventArgs e) {
  double[] vec = new double[3];
  double[,] mat = new double[3, 3];
  for (int ix = 0; ix < 3; ++ix) {
    vec[ix] = ix;
    for (int iy = 0; iy < 3; ++iy) {
      mat[ix, iy] = (ix + 1) * iy;
    }
  }
  double sum = SomeFunction(1, vec, mat);
}
[System.Runtime.InteropServices.DllImport("cpptemp8.dll")]
private static extern double SomeFunction(double a, double[] vec, double[,] mat);
1 голос
/ 03 марта 2009

Если вы не можете заставить работать решение extern и P / Invoke, вероятно, лучшим вариантом будет обертка. Создайте управляемую C ++ DLL, которая использует как управляемый, так и неуправляемый код. Добавьте класс .NET к этой DLL, который является просто оболочкой для функций в вашей C DLL. Ваш код C # может вызывать класс C ++ .NET, который, в свою очередь, будет перенаправлять функции C.

Таким образом, вы можете написать перевод между .NET и неуправляемым кодом самостоятельно, вместо того, чтобы полагаться на среду выполнения, чтобы сделать это за вас.

0 голосов
/ 04 марта 2009

используйте swig, он сгенерирует ваш пинвоук для вас

...