2010-03-25 16 views
15

Gibt es eine Möglichkeit, p/invoke Wrapper für .net von einem c-Header automatisch zu erstellen?C# -Wrapper automatisch aus c-Headern erstellen?

Natürlich könnte ich sie von Hand erstellen, aber ihre Pflege wäre schmerzhaft, und ich würde wahrscheinlich einen Fehler machen, irgendwo in schwer zu Debugging-Crashs.

Ich versuchte SWIG, aber es erstellt vollständige Klassen, in denen einfache Strukturen ausreichen würden. Ein weiteres Problem mit SWIG ist, dass es zusätzlichen Interop-Code auf der c-Seite erfordert.

Ich würde es vorziehen, wenn die Ausgabe auch mono bearbeitet, aber das ist nicht notwendig.

Eine andere Sache, mit der ich arbeiten könnte, ist ein Programm, das den c-Header analysiert und eine Ausgabe in einem schönen Zwischenformat wie xml erstellt, aus der ich den C# -Wrapper selbst erstellen kann.

Edit:
PInvoke Interop-Assistent ist das, was ich brauchte.
Es gibt jedoch einige kleine Probleme mit ihm:
* Es übersetzt "unsigned char *" zu string wo ich IntPtr
* Es geht davon aus, dass size_t = int = long = 32bit. Dies gilt derzeit für mich, aber möglicherweise nicht auf jeder Plattform.
Gibt es eine saubere Möglichkeit, das zu beheben? Sonst benutze ich ein bisschen Suchen und Ersetzen auf dem c-Code vor der Konvertierung.

Antwort

10

Die PInvoke Interop Assistant sollte besser für Sie passen, es wurde speziell entwickelt, um mit C-Code zu arbeiten.

Passen Sie einfach auf, dass kein Werkzeug Ihnen eine 100% garantierte Lösung gibt, C-Deklarationen sind Weise zu zweideutig, um ein völlig störungsfreies Ergebnis zu garantieren. Probleme durch Zeiger, die im C-Code allgegenwärtig sind. Es gibt keine Möglichkeit zu sagen, dass ein Zeiger verwendet wird, um Speicher zu lesen oder zu schreiben. Oder beides. Oder wer ist verantwortlich für die Freigabe der Erinnerung, auf die hingewiesen wird.

Dies ist ein wichtiger Aufschub für statische Code-Analysatoren, sie können nicht einen anständigen Job tun, wenn sie nicht wissen, wie ein Zeiger verwendet wird. Sie können es nur aus der Nutzung ableiten, aber das ist ein Henne-und-Ei-Problem, die Verwendung könnte falsch sein. Microsoft adressierte das Problem in ihren eigenen Headern mit SAL annotations, Extra-Markup, das für einen Compiler neutral ist, aber von einem Codeanalysator analysiert werden kann. Sie geben explizit den Verwendungszweck eines Zeigers an.

Wird auch vom Pinvoke Interop Assistant verwendet, weshalb Winapi Deklarationen besser funktionieren können. Aber das funktioniert natürlich nur mit Microsoft-Headern, diese SAL-Annotationen fehlen normalerweise auf Code, der von einem beschäftigten C-Programmierer geschrieben wurde.

+1

Ich stimme dem Interop Assistant zu. Beachten Sie jedoch, dass die GUI einen nervigen Bug hat (begrenzte Länge, ärgerlich, wenn Sie viele Headerdateien übersetzen wollen) und der generierte C# -Code für Bitfelder nicht nur wirklich hässlich, sondern auch falsch ist (dh Sie müssen * das * überprüfen) Bitfeldcode manuell). Für alles außer Bitfelder fand ich, dass es gut funktioniert, obwohl das erste, was ich mit dem Code mache, ist, die langen Namespaces ('System.Runtime.InteropServices' für jedes Attribut) zu entfernen. – OregonGhost

+1

Es gibt einige kleine Probleme damit. Es übersetzt "unsigned char *" in eine Zeichenfolge, wo ich IntPtr bevorzugen würde, und nimmt an, dass int = long = 32bit. Gibt es einen sauberen Weg, das zu beheben? Sonst werde ich ein wenig suchen und ersetzen auf dem c-Code vor der Konvertierung. – Winner

+1

Das sind die Zweideutigkeiten, vor denen ich Sie gewarnt habe. Kein sauberer Weg, die generierte P/Invoke-Deklaration basteln zu müssen ist normal. Btw: int und long ist 32-Bit in den meisten C/C++ - Code. –

1

Wenn ich Ihre Frage richtig verstehe, fragen Sie im Grunde, ob es eine Möglichkeit gibt, was SWIG macht.

Natürlich möchten Sie es ein bisschen anders machen, also wäre eine Möglichkeit, den SWIG-Code zu nehmen und ihn so zu ändern, dass er so funktioniert, wie Sie möchten.