In dem Tech Talk wurde SWIG sehr kurz erwähnt, so etwas wie "... bis wir den Schluck fertig haben ..."
StackedCrooked
1
@Matt: Wahrscheinlich möchte er eine vorhandene C ++ - Bibliothek verwenden, ohne sie nach C oder Go portieren zu müssen. Ich wollte das Gleiche.
Graeme Perrow
Ich kann mir keine anständige Bibliothek vorstellen, die für C ++ und nicht für C verfügbar ist. Ich würde gerne wissen, was Sie vorhaben.
Matt Joiner
13
@Matt: Ein Beispiel ist die Boost-Bibliothek, und es gibt Tausende anderer nützlicher C ++ - Bibliotheken. Aber vielleicht füttere ich hier nur einen Troll ...
Frank
@Matt: In meinem Fall wollte ich eine Go-Schnittstelle zu unserer vorhandenen Client-Bibliothek erstellen, aber die Bibliothek besteht hauptsächlich aus C ++. Das Portieren nach C oder Go ist einfach keine Option.
Graeme Perrow
Antworten:
154
Update: Es ist mir gelungen, eine kleine Test-C ++ - Klasse mit Go zu verknüpfen
Wenn Sie Ihren C ++ - Code mit einer C-Schnittstelle umschließen, sollten Sie in der Lage sein, Ihre Bibliothek mit cgo aufzurufen (siehe das Beispiel von gmp in $GOROOT/misc/cgo/gmp).
Ich bin mir nicht sicher, ob die Idee einer Klasse in C ++ in Go wirklich ausgedrückt werden kann, da sie keine Vererbung hat.
Seien Sie vorsichtig damit, ich habe keine Ahnung, was mit dem Speicher passieren könnte, wenn Sie ihn zwischen den beiden Sprachen senden.
Scott Wales
11
Ich muss sagen, dieses Beispiel erinnert mich daran, warum ich reines Go schreiben möchte. Schauen Sie, wie viel größer und hässlicher die C ++ - Seite ist. Ick.
Jeff Allen
@ScottWales Gibt es eine Chance, dass du dies in ein Repo auf Github oder so gesetzt hast? Ich würde gerne ein funktionierendes Beispiel sehen
netpoetica
7
@Arne: Sie stimmen eine Antwort nicht ab, weil sie nicht die beste ist. Sie stimmen eine Antwort ab, weil sie nicht hilfreich ist. Solange es funktioniert, ist diese Antwort auch dann hilfreich, wenn es bessere Lösungen gibt.
Graeme Perrow
Gute Nachrichten, Go wird jetzt cpp kompilieren, sodass das Makefile nicht mehr benötigt wird. Die unsicheren Zeiger-Wrapper haben bei mir nicht funktioniert. Eine kleine Modifikation für mich zusammengestellt: play.golang.org/p/hKuKV51cRpgo test sollte ohne das Makefile funktionieren
Drew
47
Derzeit scheint SWIG die beste Lösung dafür zu sein:
Es unterstützt die Vererbung und ermöglicht sogar die Unterklasse von C ++ - Klassen mit Go-Struktur. Wenn überschriebene Methoden in C ++ - Code aufgerufen werden, wird Go-Code ausgelöst.
Der Abschnitt über C ++ in den Go-FAQ wird aktualisiert und erwähnt nun SWIG und sagt nicht mehr " weil Go Müll gesammelt hat, ist es unklug, dies zumindest naiv zu tun ".
Ich wünschte, es gäbe eine Möglichkeit, dies zu verbessern. Die anderen Antworten sind veraltet. Plus SWIG hat swig.org/Doc3.0/Go.html
dragonx
34
Sie können noch nicht ganz von dem, was ich in den FAQ gelesen habe :
Verknüpfen Go-Programme mit C / C ++ - Programmen?
Es gibt zwei Go-Compiler-Implementierungen, gc (das 6g-Programm und Freunde) und gccgo. Gc verwendet eine andere Aufrufkonvention und einen anderen Linker und kann daher nur mit C-Programmen verknüpft werden, die dieselbe Konvention verwenden. Es gibt einen solchen C-Compiler, aber keinen C ++ - Compiler. Gccgo ist ein GCC-Frontend, das mit Sorgfalt mit GCC-kompilierten C- oder C ++ - Programmen verknüpft werden kann.
Das Programm cgo bietet den Mechanismus für eine „Fremdfunktionsschnittstelle“, um das sichere Aufrufen von C-Bibliotheken aus Go-Code zu ermöglichen. SWIG erweitert diese Funktion auf C ++ - Bibliotheken.
Ich habe das folgende Beispiel basierend auf der Antwort von Scott Wales erstellt . Ich habe es in der laufenden goVersion von macOS High Sierra 10.13.3 getestet go1.10 darwin/amd64.
(1) Code für library.hppdie C ++ - API, die wir aufrufen möchten.
#pragma once
classFoo{public:Foo(intvalue);~Foo();intvalue()const;private:int m_value;};
(2) Code für library.cppdie C ++ - Implementierung.
(3) Code für library-bridge.hdie Bridge, der erforderlich ist, um eine Cimplementierte API verfügbar zu machen, C++damit diese goverwendet werden kann.
Ich kann das Beispielprogramm wie folgt ausführen:
$ make
clang++-o liblibrary.so library.cpp library-bridge.cpp \
-std=c++17-O3 -Wall-Wextra-fPIC -shared
$ go run library.go
[c++ bridge] LIB_NewFoo(42)[c++]Foo::Foo(42)[c++ bridge] LIB_NewFoo(42) will return pointer 0x42002e0[c++ bridge] LIB_FooValue(0x42002e0)[c++]Foo::value()is42[go]42[c++ bridge] LIB_DestroyFoo(0x42002e0)[c++]Foo::~Foo(42)
Wichtig
Die obigen Kommentare import "C"im goProgramm sind NICHT OPTIONAL . Sie müssen sie genau wie gezeigt platzieren, damit Sie cgowissen, welcher Header und welche Bibliothek geladen werden sollen. In diesem Fall:
Sieht so aus, als wäre es eine der früh gestellten Fragen zu Golang. Und gleichzeitig Antworten nie zu aktualisieren. In diesen drei bis vier Jahren sind zu viele neue Bibliotheken und Blogposts erschienen. Unten sind die wenigen Links aufgeführt, die ich für nützlich hielt.
Bei Verwendung des gcc Go-Compilers gccgo wird über die Interoperabilität zwischen C und Go gesprochen. Bei der Verwendung von gccgo gibt es jedoch Einschränkungen sowohl für die Interoperabilität als auch für den implementierten Funktionsumfang von Go (z. B. eingeschränkte Goroutinen, keine Speicherbereinigung).
1. Erstellen Sie eine Sprache ohne Funktionen für die manuelle Speicherverwaltung. 2. Entfernen Sie die Speicherbereinigung. Bin ich der einzige, der sich dabei am Kopf kratzt?
György Andrasek
2
Sie betreten hier Neuland. Hier ist das Go-Beispiel für das Aufrufen von C-Code. Vielleicht können Sie so etwas tun, nachdem Sie sich mit den Konventionen zum Verwalten und Aufrufen von C ++ - Namen und vielen Versuchen und Irrtümern befasst haben.
Wenn Sie es immer noch versuchen möchten, viel Glück.
Das Problem hierbei ist, dass eine kompatible Implementierung Ihre Klassen nicht in eine kompilierte CPP-Datei einfügen muss. Wenn der Compiler die Existenz einer Klasse optimieren kann, solange sich das Programm ohne sie genauso verhält, kann sie in der ausführbaren Ausgabedatei weggelassen werden.
C hat eine standardisierte binäre Schnittstelle. Daher können Sie wissen, dass Ihre Funktionen exportiert werden. Aber C ++ hat keinen solchen Standard dahinter.
Komisch, wie viele umfassendere Themen diese Ankündigung ausgebaggert hat. Dan Lyke hatte auf seiner Website Flutterby eine sehr unterhaltsame und nachdenkliche Diskussion über die Entwicklung von Interprozessstandards , um neue Sprachen zu booten (und andere Konsequenzen, aber das ist diejenige, die hier von Bedeutung ist).
Im Wesentlichen 'Wenn dem Import von "C" unmittelbar ein Kommentar vorausgeht, wird dieser Kommentar, der als Präambel bezeichnet wird, als Header beim Kompilieren der C-Teile des Pakets verwendet. Zum Beispiel: '
Quelle: https://golang.org/cmd/cgo/
Antworten:
Update: Es ist mir gelungen, eine kleine Test-C ++ - Klasse mit Go zu verknüpfen
Wenn Sie Ihren C ++ - Code mit einer C-Schnittstelle umschließen, sollten Sie in der Lage sein, Ihre Bibliothek mit cgo aufzurufen (siehe das Beispiel von gmp in
$GOROOT/misc/cgo/gmp
).Ich bin mir nicht sicher, ob die Idee einer Klasse in C ++ in Go wirklich ausgedrückt werden kann, da sie keine Vererbung hat.
Hier ist ein Beispiel:
Ich habe eine C ++ - Klasse definiert als:
was ich in Go verwenden möchte. Ich werde die C-Schnittstelle verwenden
(Ich verwende eine
void*
anstelle einer C-Struktur, damit der Compiler die Größe von Foo kennt.)Die Implementierung ist:
Nach all dem lautet die Go-Datei:
Das Makefile, mit dem ich das kompiliert habe, war:
Versuchen Sie es mit:
Sie müssen die gemeinsam genutzte Bibliothek mit make install installieren und dann make test ausführen. Die erwartete Ausgabe ist:
quelle
go test
sollte ohne das Makefile funktionierenDerzeit scheint SWIG die beste Lösung dafür zu sein:
http://www.swig.org/Doc2.0/Go.html
Es unterstützt die Vererbung und ermöglicht sogar die Unterklasse von C ++ - Klassen mit Go-Struktur. Wenn überschriebene Methoden in C ++ - Code aufgerufen werden, wird Go-Code ausgelöst.
Der Abschnitt über C ++ in den Go-FAQ wird aktualisiert und erwähnt nun SWIG und sagt nicht mehr " weil Go Müll gesammelt hat, ist es unklug, dies zumindest naiv zu tun ".
quelle
Sie können noch nicht ganz von dem, was ich in den FAQ gelesen habe :
quelle
Ab go1.2 + integriert und kompiliert cgo automatisch C ++ - Code:
http://golang.org/doc/go1.2#cgo_and_cpp
quelle
Ich habe das folgende Beispiel basierend auf der Antwort von Scott Wales erstellt . Ich habe es in der laufenden
go
Version von macOS High Sierra 10.13.3 getestetgo1.10 darwin/amd64
.(1) Code für
library.hpp
die C ++ - API, die wir aufrufen möchten.(2) Code für
library.cpp
die C ++ - Implementierung.(3) Code für
library-bridge.h
die Bridge, der erforderlich ist, um eineC
implementierte API verfügbar zu machen,C++
damit diesego
verwendet werden kann.(4) Code für
library-bridge.cpp
die Umsetzung der Brücke.(5) Schließlich
library.go
das go-Programm, das die C ++ - API aufruft.Verwenden Sie das folgende Makefile
Ich kann das Beispielprogramm wie folgt ausführen:
Wichtig
Die obigen Kommentare
import "C"
imgo
Programm sind NICHT OPTIONAL . Sie müssen sie genau wie gezeigt platzieren, damit Siecgo
wissen, welcher Header und welche Bibliothek geladen werden sollen. In diesem Fall:Link zum GitHub-Repo mit dem vollständigen Beispiel .
quelle
Sieht so aus, als wäre es eine der früh gestellten Fragen zu Golang. Und gleichzeitig Antworten nie zu aktualisieren. In diesen drei bis vier Jahren sind zu viele neue Bibliotheken und Blogposts erschienen. Unten sind die wenigen Links aufgeführt, die ich für nützlich hielt.
SWIG und los
Aufrufen von C ++ - Code von Anfang an mit SWIG
Beim Vergleichen von Sprachen, C ++ und Go
GoForCPPProgrammierer
quelle
Bei Verwendung des gcc Go-Compilers gccgo wird über die Interoperabilität zwischen C und Go gesprochen. Bei der Verwendung von gccgo gibt es jedoch Einschränkungen sowohl für die Interoperabilität als auch für den implementierten Funktionsumfang von Go (z. B. eingeschränkte Goroutinen, keine Speicherbereinigung).
quelle
Sie betreten hier Neuland. Hier ist das Go-Beispiel für das Aufrufen von C-Code. Vielleicht können Sie so etwas tun, nachdem Sie sich mit den Konventionen zum Verwalten und Aufrufen von C ++ - Namen und vielen Versuchen und Irrtümern befasst haben.
Wenn Sie es immer noch versuchen möchten, viel Glück.
quelle
Das Problem hierbei ist, dass eine kompatible Implementierung Ihre Klassen nicht in eine kompilierte CPP-Datei einfügen muss. Wenn der Compiler die Existenz einer Klasse optimieren kann, solange sich das Programm ohne sie genauso verhält, kann sie in der ausführbaren Ausgabedatei weggelassen werden.
C hat eine standardisierte binäre Schnittstelle. Daher können Sie wissen, dass Ihre Funktionen exportiert werden. Aber C ++ hat keinen solchen Standard dahinter.
quelle
Möglicherweise müssen Sie
-lc++
dasLDFlags
für Golang / CGo hinzufügen, um die Notwendigkeit der Standardbibliothek zu erkennen.quelle
Komisch, wie viele umfassendere Themen diese Ankündigung ausgebaggert hat. Dan Lyke hatte auf seiner Website Flutterby eine sehr unterhaltsame und nachdenkliche Diskussion über die Entwicklung von Interprozessstandards , um neue Sprachen zu booten (und andere Konsequenzen, aber das ist diejenige, die hier von Bedeutung ist).
quelle
Dies kann mit dem Befehl cgo erreicht werden.
Im Wesentlichen 'Wenn dem Import von "C" unmittelbar ein Kommentar vorausgeht, wird dieser Kommentar, der als Präambel bezeichnet wird, als Header beim Kompilieren der C-Teile des Pakets verwendet. Zum Beispiel: '
Quelle: https://golang.org/cmd/cgo/
quelle