4 Stimmen

Zugriff auf nicht verwaltete C++-Funktionen von C# aus

Ich habe einige ANSI-Standard-C-Codes, die maßgebend sind. Das bedeutet, dass ich, obwohl ich den Quellcode habe, weder in eine andere Sprache übersetzen noch die Aufrufargumente ändern kann, da diese Aktionen die Autorität aufheben würden. Es gibt über 150 Funktionen.

Ich kann beiläufige Änderungen vornehmen, z. B. die Dateinamen von .C in .CPP ändern, damit es mit dem C++-Compiler von Visual Studio 2009 kompiliert werden kann, was ich getan habe. Compilerdirektiven und dergleichen können ebenfalls hinzugefügt werden. Falls erforderlich, kann ich auch eine Wrapper-Ebene einfügen.

Eine weitere Einschränkung ist, dass mein Unternehmen no wollen, dass ich die unsicher Schlüsselwort in jedem C#-Code.

Ich muss auf diese Funktionen von einem C#-Programm aus zugreifen.

Eine typische C/C++-Funktion sieht wie folgt aus:
double SomeFunction(double a, double[3] vec, double[3][3] mat);
Wobei der Inhalt des Arrays manchmal Eingabe, manchmal Ausgabe und selten beides ist.

Ich habe zunächst versucht, eine nicht verwaltete DLL zu erstellen (mit den als Extern C gekennzeichneten Funktionen). Funktionen mit nur einfachen Argumenten (int, double) funktionierten gut, aber ich konnte nicht herausfinden, wie man die Arrays marshalen kann. (Tatsächlich habe ich einige Beispielcodes gefunden, aber sie waren extrem komplex und es war unvernünftig, sie 150 Mal zu duplizieren).

Ich habe dann zwei Projekte innerhalb derselben Lösung ausprobiert, eines in C++ und das andere in C#. Im C++-Projekt habe ich eine verwaltete Funktion erstellt, die lediglich die ursprüngliche Funktion aufrief, die als nicht verwaltet gekennzeichnet war. Das war extrem sauber und einfach, und auch hier funktionierten einfache Argumente problemlos. Aber für Arrays konnte ich nicht herausfinden, wie man die Argumenttypen über die Grenze zwischen C# und C++ hinweg anpasst:
_Argument '2': cannot convert from 'double[]' to 'double*'_
(und wie oben erwähnt, kann ich unsafe nicht verwenden, um einen Zeiger zu erhalten).

Das, was ich vorhabe, muss natürlich möglich sein.
Wie kann man diese Funktionen am besten erreichen?
(Ein Beispielcode, der die obige Funktion verwendet, wäre wirklich cool).

4voto

Hans Passant Punkte 894572

Beispiel einer C/C++-Implementierung:

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;
}

Beispiel für die Verwendung von 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);

1voto

Andy Punkte 29060

Wenn Sie die Extern- und P/Invoke-Lösung nicht zum Laufen bringen können, ist ein Wrapper wahrscheinlich die beste Lösung. Erstellen Sie eine verwaltete C++-DLL, die sowohl verwalteten als auch nicht verwalteten Code verwendet. Fügen Sie dieser DLL eine .NET-Klasse hinzu, die nur ein dünner Wrapper für die Funktionen in Ihrer C-DLL ist. Ihr C#-Code kann die C++-.NET-Klasse aufrufen, die ihrerseits die C-Funktionen weiterleiten wird.

Auf diese Weise können Sie die Übersetzung zwischen .NET und nicht verwaltetem Code selbst schreiben, anstatt sich darauf zu verlassen, dass die Laufzeitumgebung dies für Sie erledigt.

0voto

patrick Punkte 14856

Verwenden Sie Swig, es wird Ihren Pinvoke für Sie erstellen

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X