我正在为C ++类开发Python绑定,扩展了std::vector
实例化。为了让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 ++类型({ {1}})到包装类。此外,在创建切片时,我需要先“手动”将Column *
转换为Column*
,然后再将其插入PyList。
我该怎么做?
答案 0 :(得分:3)
对于使用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特定代码“污染”“普通”头文件的情况下执行此操作。