2009-03-02 10 views
4

Ich habe einige ANSI-Standard-C-Code, der autorisierend ist. Das heißt, obwohl ich die Quelle habe, kann ich nicht in eine andere Sprache übersetzen oder Aufrufargumente ändern, da diese Aktionen die Autorität ungültig machen würden. Es gibt über 150 Funktionen.Getting in unmanaged C++ - Funktionen von C#

Ich kann zufällige Änderungen vornehmen, z. B. die Dateinamen von .C zu .CPP ändern, so dass es mit dem C++ - Compiler von Visual Studio 2009 kompiliert, was ich getan habe. Compiler-Anweisungen und dergleichen können ebenfalls hinzugefügt werden. Ich kann bei Bedarf auch eine Wrapper-Ebene durchlaufen.

Eine weitere Einschränkung ist meine Firma tut nicht wollen, dass ich die unsicher Schlüsselwort in jedem C# -Code verwenden.

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

Eine typische C/C++ Funktion sieht wie folgt aus:
double SomeFunction(double a, double[3] vec, double[3][3] mat);
Wo der Inhalt des Arrays sind manchmal Eingang, manchmal Ausgang und selten beides.

Ich habe zuerst versucht, eine nicht verwaltete DLL (mit den Funktionen Extern C markiert). Funktionen mit nur einfachen Argumenten (int, double) funktionierten gut, aber ich konnte nicht bestimmen, wie man die Arrays marshale. (Tatsächlich fand ich einige Beispielcode, aber es war extrem komplex und unvernünftig, 150 Mal zu duplizieren.)

Ich versuchte dann zwei Projekte innerhalb der gleichen Lösung, eins in C++ und das andere in C#. Im C++ - Projekt habe ich eine verwaltete Funktion erstellt, die nur die ursprüngliche Funktion aufruft, die als nicht verwaltet markiert wurde. Das war extrem sauber und einfach, und wieder einmal, einfache Argumente funktionierten gut. Aber für Arrays konnte ich nicht finden, wie die Argumenttypen über die Grenze von C# zu C++ passen:
Argument '2': cannot convert from 'double[]' to 'double*'
(und wie oben erwähnt, kann ich nicht unsicher verwenden, um einen Zeiger zu bekommen).

Sicherlich, was ich versuche zu tun, muss möglich sein.
Was ist der beste Weg, um diese Funktionen zu bekommen?
(Beispielcode mit der oben genannten Funktion wäre wirklich cool.)

Antwort

4

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

Probe C# Nutzung:

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

Ah, danke! Der Schlüssel für dieses Problem war, dass in C++ das Array als double [] [] deklariert ist, aber in C# als double [,]. Obwohl ersteres legale C# -Syntax ist, repräsentiert es nicht dieselbe interne Organisation. Ohne diesen Schlüssel der Einsicht würde es nicht funktionieren. –

1

Wenn Sie die externe und P/Invoke-Lösung nicht funktionieren können, ist ein Wrapper wahrscheinlich die beste Wahl. Erstellen Sie eine verwaltete C++ - DLL, die verwalteten und 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 wiederum die C-Funktionen weiterleitet.

Auf diese Weise können Sie die Übersetzung zwischen .NET und nicht verwaltetem Code selbst schreiben, statt sich auf die Laufzeit zu verlassen, um dies für Sie zu tun.

0

Verwendung swig, ist es Ihre pinvoke generieren wird für Sie