我正在为 C++ 类开发 Python 绑定(bind),该类扩展了 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++ 类型 ( Column *
) 转换为包装类。另外,在创建切片时,我需要“手动”转换 Column*
至PyObject*
在将其插入 PyList 之前。
我该怎么做?
最佳答案
我认为 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的要求MutableSequence 。 (我认为这应该足以实现您在 Python 端寻找的目标,您可能还需要使用 -extranative
调用 SWIG)。
还可能值得注意 - 对于您当前的__getitem__
您可以使用以下内容在 SWIG 接口(interface)文件中声明和定义它:
%extend MetaData {
Column* __getitem__(int i) { return (*self)[i]; }
};
这允许您在不使用 SWIG+Python 特定代码“污染”您的“正常”头文件的情况下执行此操作。
关于c++ - 如何处理我的 C++ __getitem__ 函数中的切片(由 SWIG 使用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8218314/