Swig неправильно определяет структуру для вызова C++

Я пытаюсь использовать структуру 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, которая неправильно соединяет обе структуры, но я понятия не имею, как это исправить.

Вам не нужны карты типов для Edge, просто используйте карты типов по умолчанию. Проблема в том, что ваши карты типов неверны, вы не можете преобразовать объект Go в объект C/C++ с помощью простого приведения.

Criminal_Affair_At_SO 01.03.2024 20:56

Я удалил typemap из example.i, поэтому он использует значения по умолчанию, но я все равно получаю ту же ошибку @Criminal_Affair_At_SO

Daniel Benedí 04.03.2024 10:54

Почему вы переопределяете тип Edge в Go? Обычно определения SWIG достаточно? Я думаю, что таким образом вы создаете другой тип с похожим именем. Извините, я очень хорошо знаю SWIG, но не занимаюсь Го. Вы видели github.com/swig/swig/tree/master/Examples/go/simple ? Он содержит именно то, что вы пытаетесь сделать.

Criminal_Affair_At_SO 04.03.2024 14:41

Я пытался использовать структуру Go в своем коде на C++, поэтому переопределил ее. Но теперь я думаю, что, возможно, неправильно понял философию SWIG. Я перепишу свой код на Голанге

Daniel Benedí 05.03.2024 09:48

Извините, я вас неправильно понял. Использовать структуру языка более высокого уровня от SWIG всегда сложно.

Criminal_Affair_At_SO 05.03.2024 16:37
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Объявите типы на обоих языках, как вы это сделали.

Игнорируйте тип 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++. Большое спасибо!

Daniel Benedí 08.03.2024 17:43

Другие вопросы по теме

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

Функция сортировки слиянием не работает, если размер вектора не равен 2^n
Захват указателя функции в качестве ссылки приводит к сбою сегмента
Чтение com-порта с помощью библиотеки asio. Контрольная сумма не совпадает. Питон->С++
Почему можно использовать возврат лямбды, переданной в качестве аргумента аргумента функции constexpr, в константном выражении внутри функции?
Включение и проверка битовой четности между C++ и Python
Какова продолжительность хранения и время существования параметра шаблона, не являющегося типом, и как его можно использовать для вычислений во время компиляции?
Получение TLE в вопросе 212 по лит-коду - поиск слов 2 с использованием обратного отслеживания даже после обрезки, как мне его еще оптимизировать
Динамическое размещение C++ в while(true)
Концепции C++20 и неполные типы
Максимизация суммы смежных сумм в массиве