如何在我的c++ __getitem__函数中处理切片(由SWIG使用)

How to handle slices in my C++ __getitem__ function (to be used by SWIG)

本文关键字:切片 SWIG 使用 处理 函数 我的 c++ getitem      更新时间:2023-10-16

我正在为扩展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*

我该怎么做?

我认为对于std::vector使用SWIG+Python有一个更简单的解决方案。SWIG的Python代码生成已经支持很好地包装一些STL容器。

如果您在模块接口的开头添加:

%include "pyabc.i"
%include "std_vector.i" // Assuming you don't already

和其他地方,如果你没有这样做:

%template(MetaDataBase) std::vector<Column*>;

,这将导致包装的std::vector满足Python的mutablessequence的要求。(我认为这应该足以实现您在Python方面所寻找的,您可能还需要使用-extranative调用SWIG)。

同样值得注意的是-对于当前的__getitem__,您可以在SWIG接口文件中声明和定义它,使用如下内容:

%extend MetaData {
   Column* __getitem__(int i) { return (*self)[i]; }
};

允许你这样做,而不会用SWIG+Python特定的代码"污染"你的"正常"头文件。