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

发布于 2024-12-17 07:57:36 字数 769 浏览 1 评论 0原文

我正在为 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++ 类型 (Column *) 转换为包装类。另外,在创建切片时,我需要“手动”将 Column* 转换为 PyObject*,然后再将其插入 PyList。

我该怎么做呢?

I am developing Python bindings for a C++ class which extends a std::vector instantiation. To get a Python subscript operator working for this class I added __getitem__ function looking as follows (I cut irrelevant code and error handling):

class Column;

typedef vector<Column*> MetaDataBase;

class MetaData : public MetaDataBase {
public:

#ifdef SWIGPYTHON
Column* __getitem__(int i) { return (*this)[i]; }
#endif
};

The above works all right in Python for accessing single elements, but it does not work for slices.

OK, so I understand I need to change type of the function's parameter to PyObject * and use PySlice_Check to see if the function is supposed to return a PyList.

This is fine, no problem with that. But because I have to return PyList from the function sometimes, the type of the __getitem__ return value has to be PyObject* as well and I cannot rely on SWIG to convert my C++ type (Column *) to a wrapper class. Also, when creating a slice, I need to 'manually' convert Column* to PyObject* before inserting it into the PyList.

How can I do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浮光之海 2024-12-24 07:57:36

我认为对于带有 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特定代码。

I think there's a much simpler solution to this for std::vector with SWIG+Python. SWIG's Python code generation already has support for doing quite a good job wrapping some STL containers.

If you add to the beginning of your module interface:

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

and somewhere, if you haven't done so:

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

then this will cause the wrapped std::vector to meet the requirements of Python's MutableSequence. (I think this should be sufficient to achieve what you're looking for on the Python side, you might need to call SWIG with -extranative as well).

Also worth noting possibly - for your current __getitem__ you can declare and define it in the SWIG interface file using something like:

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

Which allows you to do this without "polluting" your "normal" header files with SWIG+Python specific code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文