Я пытаюсь подключить библиотеку C ++ к серверу приложений, написанному на Go. Цель состоит в том, чтобы и библиотека C ++, и сервер приложений работали над общей структурой данных, что означает, что:
Я немного поигрался с cgo и подключил C ++, и все до сих пор работало … Однако, когда дело доходит до обмена указателями на структуры данных, я теряюсь. Что я пробовал до сих пор:
//c++ library header: xyz.h
#include <stdlib.h>
class CppLib {
public:
CppLib(unsigned int input);
int * CreateArray();
};
//C++ library implementation: xyz.cpp
#include "xyz.h"
CppLib::CppLib(unsigned int input) {
_input = input;
}
int * CppLib::CreateArray() {
int values = 5;
int * myPointer = new int [values];
for (unsigned i = 0; i < values; ++i) {
myPointer[i] = i;
}
return myPointer;
}
Реализация интерфейса выглядит так:
//interface.h
int * CCreateArray();
//interface.cc
#include "../lib/xyz.h"
extern "C" {
int * CCreateArray() {
CppLib lib(1);
return lib.CreateArray();
}
}
Наконец, реализация go выглядит следующим образом:
package cgo_lib
// #cgo CFLAGS: -I../lib
// #cgo LDFLAGS: -L../lib -linterfacelib
// #include "interface.h"import "C"
func GoCreateArray() *int {
return *int(C.CCreateArray())
}
При компиляции я получаю следующую ошибку:
# cgo_lib
../cgo_lib/cgo_lib.go:13: cannot convert _Cfunc_CCreateArray() (type *C.int) to type int
../cgo_lib/cgo_lib.go:13: invalid indirect of int(_Cfunc_CCreateArray()) (type int)
Поэтому мой вопрос: как обмениваться указателями на структуры данных между C ++ и Go. Выше я только что описал путь от C ++ до GO, но я также заинтересован в обратном.
Большое спасибо за вашу помощь заранее.
Это здесь:
return *int(C.CCreateArray())
можно записать как
return *((int)(C.CCreateArray()))
Вы ссылаетесь на int
что приводит к:
invalid indirect of int(_Cfunc_CCreateArray()) (type int)
И внутри этого заявления, соблюдая только эту часть:
(int)(C.CCreateArray())
Вы пытаетесь преобразовать *C.int
для int
, который не будет работать, потому что первый указатель, а второй нет.
Помимо этой проблемы с управлением памятью, о которой @tadman упоминает в комментариях к вашему вопросу, Go не представляет массивы как указатели на их первый элемент, как это делает C.
Если вы хотите поделиться int
s вы должны будете точно указать их ширину: int
в Go имеет ширину, зависящую от арки, а также C int
,
Узнайте больше о CGO: http://golang.org/cmd/cgo/
Как только вы исправите все эти проблемы, вам нужно будет выполнить что-то вроде этого:
s := make([]int32, 0, 0)
h := (*reflect.SliceHeader)((unsafe.Pointer)(&s))
h.Data, h.Len, h.Cap = P, L, L // see below
s = *(*[]int32)(h)
где P
идет uintptr
в ваш массив, который вы создали в C ++ и L
длина массива в Go int