Swig结构体识别异常:Go与C++交互时类型不匹配报错
Go与C++通过SWIG交互时结构体类型不匹配错误
错误信息
./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; } }
问题根源
- SWIG会为C++的
Edge结构体自动生成Go接口,包含GetW、SetW等访问方法,自定义的Edge结构体未实现这些方法,因此无法被当作example.Edge类型传入Process函数。 - 原SWIG的
Edge*typemap配置错误:$1 = *($1_ltype*)($input);会对传入的指针进行解引用,导致试图把指针指向的结构体赋值给指针变量,类型完全不匹配。
修复方案
步骤1:修正SWIG的typemap配置
修改./example/example.i,删除错误的Edge值类型typemap,正确配置Edge*的指针传递:
%module example // 正确处理Edge指针:直接将传入的Go指针转换为C++指针 %typemap(in) Edge* { $1 = ($1_ltype)$input; } %{ #include "example.h" %} %include "example.h"
步骤2:使用SWIG生成的Edge类型
不要自定义Go版Edge,直接使用SWIG生成的example.Edge,保证类型兼容:
修改./runme.go为:
package main import ( "unsafe" "simple/example" ) func main() { // 使用SWIG生成的example.Edge构建数据 data := []example.Edge{ {X: 1, Y: 2, W: 1.0}, {X: 1, Y: 3, W: 4.0}, {X: 2, Y: 3, W: 3.0}, {X: 2, Y: 4, W: 0.5}, } // 获取切片首元素的指针,直接转换为example.Edge* dataPtr := unsafe.Pointer(&data[0]) example.Process((*example.Edge)(dataPtr), int64(len(data)), int64(4)) }
步骤3:重新生成SWIG绑定
重新运行SWIG命令生成Go绑定代码,例如:
swig -go -cgo -intgosize 64 example/example.i
修改后,Go代码使用的是SWIG生成的与C++结构体兼容的类型,指针传递符合要求,即可正常调用Process函数。
内容的提问来源于stack exchange,提问作者Daniel Benedí
相关产品推荐
相关产品推荐

