Обмен структурами данных (массивами) между Go (golang) и переполнением стека

Я пытаюсь подключить библиотеку C ++ к серверу приложений, написанному на Go. Цель состоит в том, чтобы и библиотека C ++, и сервер приложений работали над общей структурой данных, что означает, что:

  1. Сервер приложений Go может обращаться к массиву, созданному библиотекой C ++.
  2. Библиотека C ++ может работать с массивом, созданным сервером приложений Go.

Я немного поигрался с 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, но я также заинтересован в обратном.

Большое спасибо за вашу помощь заранее.

1

Решение

Это здесь:

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.

Если вы хотите поделиться ints вы должны будете точно указать их ширину: 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

1

Другие решения