如何在SWIG中重新定义类方法签名以使用自定义类型映射?
解决SWIG中类方法无法应用输出参数typemap的问题
要让类方法SampleClass::two_args也能像全局函数那样将std::vector<int>*转为Python输出参数,你需要调整SWIG接口文件的写法——直接重新声明类方法签名无效,得结合%ignore和%extend来实现,具体步骤如下:
修改SWIG接口文件(interface.i)
替换原接口中类方法的无效声明,改为以下内容:
%module example %{ #include "example.hpp" %} %include "typemaps.i" %include "std_vector.i" %template(doublevector) std::vector<double>; %template(intvector) std::vector<int>; /* NOTE: This mostly works but not for constructor */ %apply std::vector<double> *INPUT {std::vector<double>* }; /* Ignore vec as input argument and set it to a temp val */ %typemap(in, numinputs=0) std::vector<int>* VecOutInt (std::vector<int> tmp){ $1 = &tmp; } /* Return a list to python */ %typemap(argout) std::vector<int>* VecOutInt { size_t size = (*$1).size(); $result = PyList_New(size); Py_ssize_t idx = 0; for (idx = 0; idx < size; ++idx){ PyObject *o = PyLong_FromLong($1->at(idx)); PyList_SetItem($result, idx, o); } } // 全局函数正常重声明 void some_func(int x, int y, std::vector<int> * VecOutInt); // 关键修改:先忽略原类方法,再通过%extend重新定义 %ignore SampleClass::two_args; %include "example.hpp" %extend SampleClass { void two_args(int x, int y, std::vector<int>* VecOutInt) { // 调用原始类方法逻辑 $self->two_args(x, y, VecOutInt); } }
原理说明
- %ignore SampleClass::two_args:告诉SWIG忽略头文件中原本的
two_args方法声明,避免生成不符合需求的绑定代码。 - %extend SampleClass:动态扩展
SampleClass,重新定义two_args的签名并绑定到你的自定义typemap上,内部调用原始类方法实现逻辑,保证功能不变。
测试Python调用
修改后重新编译SWIG生成绑定,Python调用即可正常返回列表:
>>> import example >>> cls = example.SampleClass() >>> res = cls.two_args(1, 2) >>> res [1, 2]
另一种简化方案:如果不想用%extend,也可以直接用%apply将typemap匹配到类方法的参数名上,在%include "example.hpp"前添加:
%apply std::vector<int>* VecOutInt { std::vector<int>* vec };
这样SWIG会自动将你的typemap应用到SampleClass::two_args中名为vec的参数上,同样无需修改C++代码。
内容的提问来源于stack exchange,提问作者LateBird
相关产品推荐
相关产品推荐

