Как использовать C++ в Движении?

На новом языке Движения, как я называю код C++? Другими словами, как я могу обернуть свои классы C++ и использовать их в Движении?

157
задан Flimzy 22 November 2019 в 11:40
поделиться

6 ответов

Обновление: Мне удалось связать небольшой тестовый класс C ++ с Go

Если вы оберните свой код C ++ интерфейсом C, вы сможете вызывать свою библиотеку с помощью cgo (см. Пример gmp в $ GOROOT / misc / cgo / gmp ).

Я не уверен, действительно ли идея класса в C ++ выражается в Go, поскольку он не имеет наследования.

Вот пример:

У меня есть класс C ++, определенный как:

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

, который я хочу использовать в Go. Я буду использовать интерфейс C

// foo.h
#ifdef __cplusplus
extern "C" {
#endif
  typedef void* Foo;
  Foo FooInit(void);
  void FooFree(Foo);
  void FooBar(Foo);
#ifdef __cplusplus
}
#endif

(я использую void * вместо структуры C, чтобы компилятор знал размер Foo)

Реализация следующая:

//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();
}

со всем, что сделано , файл Go:

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

Makefile, который я использовал для его компиляции, был:

// 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)

Попробуйте протестировать его с помощью:

// foo_test.go
package foo
import "testing"
func TestFoo(t *testing.T){
    foo := New();
    foo.Bar();
    foo.Free();
}

Вам нужно будет установить разделяемую библиотеку с помощью make install, затем запустить make test. Ожидаемый результат:

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
141
ответ дан 23 November 2019 в 21:45
поделиться

Из того, что я прочитал в FAQ , вы еще не понимаете:

Связываются ли программы Go с программами C / C ++?

Есть два Go реализации компилятора, gc (программа 6g и ее друзья) и gccgo. Gc использует другое соглашение о вызовах и компоновщик, поэтому его можно связывать только с программами на C, используя то же соглашение. Такой компилятор C есть, но компилятора C ++ нет. Gccgo - это интерфейс GCC, который можно с осторожностью связать с программами C или C ++, скомпилированными GCC.

Программа cgo предоставляет механизм для «интерфейса внешней функции», позволяющий безопасно вызывать библиотеки C из кода Go. . SWIG расширяет эту возможность до библиотек C ++.

33
ответ дан 23 November 2019 в 21:45
поделиться

Говорят о взаимодействии между C и Go при использовании компилятора gcc Go, gccgo. Однако существуют ограничения как для взаимодействия, так и для реализованного набора функций Go при использовании gccgo (например, ограниченные горутины, отсутствие сборки мусора).

3
ответ дан 23 November 2019 в 21:45
поделиться

Здесь вы идете по неизведанной территории. Здесь - пример Go для вызова кода C,

2
ответ дан 23 November 2019 в 21:45
поделиться

Проблема здесь в том, что совместимой реализации не требуется помещать ваши классы в файл компиляции .cpp. Если компилятор может оптимизировать существование класса, при условии, что программа ведет себя одинаково без него, то его можно исключить из выходного исполняемого файла.

C имеет стандартизованный двоичный интерфейс. Таким образом, вы сможете узнать, что ваши функции экспортированы. Но в C ++ такого стандарта нет.

1
ответ дан 23 November 2019 в 21:45
поделиться

Забавно, сколько более общих вопросов затронуло это объявление. Дэн Лайк провел очень интересную и вдумчивую дискуссию на своем веб-сайте Flutterby о разработке межпроцессных стандартов как способе начальной загрузки новых языков (и других ответвлений, но это единственное, что здесь уместно).

1
ответ дан 23 November 2019 в 21:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: