我正在为一个扩展std::vector
实例化的C++类开发Python绑定。为了让Python下标运算符对这个类起作用,我添加了__getitem__
函数,如下所示(我去掉了不相关的代码和错误处理):
class Column;
typedef vector<Column*> MetaDataBase;
class MetaData : public MetaDataBase {
public:
#ifdef SWIGPYTHON
Column* __getitem__(int i) { return (*this)[i]; }
#endif
};
在Python中,上面的方法可以很好地访问单个元素,但不适用于切片。
好了,我知道我需要将函数的参数类型更改为PyObject *
,并使用PySlice_Check
来查看函数是否应该返回PyList
。
这很好,没有问题。但是因为我有时必须从函数返回PyList
,所以__getitem__
返回值的类型也必须是PyObject*
,并且我不能依赖SWIG将我的C++类型(Column *
)转换为包装类。此外,在创建切片时,在将其插入到PyList之前,我需要“手动”将Column*
转换为PyObject*
。
我该怎么做呢?
发布于 2011-11-22 19:13:55
我认为对于使用SWIG+Python的std::vector
来说,有一个简单得多的解决方案。SWIG的Python代码生成已经支持对一些STL容器进行很好的包装。
如果在模块接口的开头添加:
%include "pyabc.i"
%include "std_vector.i" // Assuming you don't already
在某个地方,如果你还没有这样做:
%template(MetaDataBase) std::vector<Column*>;
然后,这将使包装的std::vector
满足Python的MutableSequence的要求。(我认为这应该足以在Python端实现您正在寻找的东西,您可能还需要使用-extranative
调用SWIG )。
同样值得注意的是,对于您当前的__getitem__
,您可以在SWIG接口文件中使用如下内容来声明和定义它:
%extend MetaData {
Column* __getitem__(int i) { return (*self)[i]; }
};
这允许您在不使用特定于SWIG+Python的代码“污染”您的“正常”头文件的情况下执行此操作。
https://stackoverflow.com/questions/8218314
复制相似问题