Mise à jour : J'ai réussi à lier une petite classe C++ de test avec Go
Si vous enveloppez votre code C++ avec une interface C, vous devriez être en mesure d'appeler votre bibliothèque avec cgo (voir l'exemple de gmp dans $GOROOT/misc/cgo/gmp
).
Je ne suis pas sûr que l'idée d'une classe en C++ soit vraiment exprimable en Go, car il n'y a pas d'héritage.
Voici un exemple :
J'ai une classe C++ définie comme :
// foo.hpp
class cxxFoo {
public:
int a;
cxxFoo(int _a):a(_a){};
~cxxFoo(){};
void Bar();
};
// foo.cpp
#include <iostream>
#include "foo.hpp"
void
cxxFoo::Bar(void){
std::cout<<this->a<<std::endl;
}
que je veux utiliser dans Go. Je vais utiliser l'interface C
// foo.h
#ifdef __cplusplus
extern "C" {
#endif
typedef void* Foo;
Foo FooInit(void);
void FooFree(Foo);
void FooBar(Foo);
#ifdef __cplusplus
}
#endif
(J'utilise un void*
au lieu d'un struct C pour que le compilateur connaisse la taille de Foo)
La mise en œuvre est :
//cfoo.cpp
#include "foo.hpp"
#include "foo.h"
Foo FooInit()
{
cxxFoo * ret = new cxxFoo(1);
return (void*)ret;
}
void FooFree(Foo f)
{
cxxFoo * foo = (cxxFoo*)f;
delete foo;
}
void FooBar(Foo f)
{
cxxFoo * foo = (cxxFoo*)f;
foo->Bar();
}
avec tout cela fait, le fichier Go est :
// foo.go
package foo
// #include "foo.h"
import "C"
import "unsafe"
type GoFoo struct {
foo C.Foo;
}
func New()(GoFoo){
var ret GoFoo;
ret.foo = C.FooInit();
return ret;
}
func (f GoFoo)Free(){
C.FooFree(unsafe.Pointer(f.foo));
}
func (f GoFoo)Bar(){
C.FooBar(unsafe.Pointer(f.foo));
}
Le makefile que j'ai utilisé pour compiler ceci était :
// makefile
TARG=foo
CGOFILES=foo.go
include $(GOROOT)/src/Make.$(GOARCH)
include $(GOROOT)/src/Make.pkg
foo.o:foo.cpp
g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $<
cfoo.o:cfoo.cpp
g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $<
CGO_LDFLAGS+=-lstdc++
$(elem)_foo.so: foo.cgo4.o foo.o cfoo.o
gcc $(_CGO_CFLAGS_$(GOARCH)) $(_CGO_LDFLAGS_$(GOOS)) -o $@ $^ $(CGO_LDFLAGS)
Essayez de le tester avec :
// foo_test.go
package foo
import "testing"
func TestFoo(t *testing.T){
foo := New();
foo.Bar();
foo.Free();
}
Vous devrez installer la bibliothèque partagée avec make install, puis lancer make test. La sortie attendue est :
gotest
rm -f _test/foo.a _gotest_.6
6g -o _gotest_.6 foo.cgo1.go foo.cgo2.go foo_test.go
rm -f _test/foo.a
gopack grc _test/foo.a _gotest_.6 foo.cgo3.6
1
PASS
1 votes
Dans la présentation technique, SWIG a été très brièvement mentionné, quelque chose comme " jusqu'à ce que nous ayons terminé le swig ".
1 votes
@Matt : Il veut probablement utiliser une bibliothèque C++ existante sans avoir à la porter en C ou en Go. Je voulais la même chose.
0 votes
Je ne connais pas une seule bibliothèque décente disponible pour le C++ et pas pour le C. J'aimerais savoir ce que vous avez en tête.
13 votes
@Matt : Un exemple est la bibliothèque Boost, et il y a des milliers d'autres bibliothèques C++ utiles. Mais peut-être que je ne fais que nourrir un troll ici ...
0 votes
@Matt : dans mon cas, je voulais faire une interface Go pour notre bibliothèque client existante mais la bibliothèque est principalement en C++. La porter en C ou en Go n'est tout simplement pas envisageable.
0 votes
@Graeme Perrow : Essaie de lui donner une interface C.
0 votes
@Matt : Notre bibliothèque a une interface C mais le chargement de la DLL, implémentée en C++, ne fonctionnerait pas parce que les éléments d'exécution C++ étaient manquants.
0 votes
Puis-je utiliser SWIG avec du code Windows C++ ?
0 votes
github.com/charleslaw/static-cgo est un exemple de travail