2009-03-02 2 views
4

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

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

Другим ограничением является моя компания делает не хочет меня использовать небезопасный ключевое слово в любом C# код.

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

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

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

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

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

ответ

4

Образец 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); 
+0

Ах, спасибо! Ключом к этой проблеме было то, что в C++ массив объявляется как double [] [], но в C# как double [,]. Хотя первый является законным синтаксисом C#, он не представляет собой ту же внутреннюю организацию. Без этой ключевой части проницательности это не сработает. –

1

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

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

0

использование SWIG, он будет генерировать свой PInvoke для вас

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