Я пытаюсь использовать структуру Golang в коде С++. Для этого я определил одну и ту же структуру как в заголовке C++, так и в Golang, но когда я пытаюсь запустить проект, я получаю следующую ошибку:
./runme.go:22:32: cannot use (*Edge)(dataPtr) (value of type *Edge) as example.Edge value in argument to example.Process: *Edge does not implement example.Edge (missing method GetW)
Мой проект имеет следующую структуру.
./go.mod:
module simple
go 1.20
./runme.go:
package main
import (
"unsafe"
"simple/example"
)
type Edge struct {
X, Y int64
W float64
}
func main() {
data := []Edge {
{1,2,1.0},
{1,3,4.0},
{2,3,3.0},
{2,4,0.5},
}
dataPtr := unsafe.Pointer(&data[0])
example.Process((*Edge)(dataPtr),int64(len(data)), int64(4))
}
Затем у меня есть пакет, содержащий код С++:
./example/package.go:
package example
import "C"
./example/example.i:
%module example
// Typemaps for Edge struct
%typemap(in) Edge {
$1 = *($1_ltype*)($input);
}
%typemap(in) Edge* {
$1 = *($1_ltype*)($input);
}
%typemap(out) Edge {
$result = new $1_btype($1);
}
%{
#include "example.h"
%}
%include "example.h"
./example/example.h:
#ifndef EXAMPLE_H
#define EXAMPLE_H
typedef struct Edge
{
long int X, Y;
double W;
} Edge;
void Process(Edge *G, long int M, long int N);
#endif
./example/example.cpp:
#include "example.h"
#include <iostream>
void Process(Edge *G, long int M, long int N) {
// Do some work with the Edge list
std::cout << "|V| = " << N << " -- |E| = " << M << std::endl;
for(int i = 0; i < M; i++) {
std::cout << "(" << G[i].X << ", " << G[i].Y << ") = " << G[i].W << std::endl;
}
}
Я пытался реализовать GetW и все остальные методы, которые он запрашивает, но в какой-то момент он запрашивает методы, которые я не понимаю, что они означают. Я считаю, что проблема может быть в карте типов в интерфейсе swig, которая неправильно соединяет обе структуры, но я понятия не имею, как это исправить.
Я удалил typemap из example.i, поэтому он использует значения по умолчанию, но я все равно получаю ту же ошибку @Criminal_Affair_At_SO
Почему вы переопределяете тип Edge в Go? Обычно определения SWIG достаточно? Я думаю, что таким образом вы создаете другой тип с похожим именем. Извините, я очень хорошо знаю SWIG, но не занимаюсь Го. Вы видели github.com/swig/swig/tree/master/Examples/go/simple ? Он содержит именно то, что вы пытаетесь сделать.
Я пытался использовать структуру Go в своем коде на C++, поэтому переопределил ее. Но теперь я думаю, что, возможно, неправильно понял философию SWIG. Я перепишу свой код на Голанге
Извините, я вас неправильно понял. Использовать структуру языка более высокого уровня от SWIG всегда сложно.





Объявите типы на обоих языках, как вы это сделали.
Игнорируйте тип C++ из SWIG:
%ignore Edge;
SWIG генерирует обертку Go с подписями Go, в этой оболочке должен быть объявлен тип Go Edge, импортируйте его с помощью:
%insert(go_wrapper) %{
// import here
%}
SWIG также должен знать, как использовать правильный тип в обертке, для этого используйте специальную карту типов gotype:
%typemap(gotype) Edge "root.Edge"
Не забудьте проверить файл example/example.go — в нем будет что-то вроде:
func Process(arg1 Edge, arg2 int64, arg3 int64) {
Это корень вашей проблемы. Карта типов gotype должна это исправить.
Извините, но у меня есть лишь очень базовое понимание Go.
Хорошо, наконец-то мне удалось заставить это работать. Мне также нужно было добавить %typemap(gotype) Edge* "*graph.Edge", чтобы можно было использовать указатели для передачи массива/среза. Более того, example/example.go добавляет импорт в другую позицию, чем остальные, поэтому мне пришлось его переместить. Кроме того, мне не хватало флага -c++. Большое спасибо!
Вам не нужны карты типов для
Edge, просто используйте карты типов по умолчанию. Проблема в том, что ваши карты типов неверны, вы не можете преобразовать объект Go в объект C/C++ с помощью простого приведения.