【问题标题】:How to get python slicing to work with my c++ array class using SWIG如何使用 SWIG 让 python 切片与我的 c++ 数组类一起使用
【发布时间】:2014-04-21 22:03:40
【问题描述】:

我有一个数组类,Array1D,用 c++ 定义,它基本上包装了 STL 向量类。我扩展了这个类,以便可以显示数组向量的各个元素。这是我的 SWIG 接口文件中的相关代码:

namespace std{
    %template(dblVector) vector<double>;
}

%extend Array1D{
    double __getitem__(int index) {
        return (*self)[index];
    }
}

这允许我在 python 中访问数组的各个元素:

>>> a = Array1D(10) # creates a c++ vector of length 10 with zeros
>>> a[0]
>>> 0

例如,我希望能够调用 a[1:3],但是,当我尝试这个时,我得到了一个 TypeError:

TypeError: in method 'Array1D___getitem__', argument 2 of type 'int'

【问题讨论】:

    标签: python c++ arrays swig


    【解决方案1】:

    问题在于,python 在调用 getitem 的切片变体时传递了一个 Slice 对象,而您的函数定义需要一个 int。您需要编写一个以 PyObject* 作为参数的 getitem 版本,然后您必须在那里实现向量的切片。

    我在写这篇文章时并没有进行实际测试,所以请谨慎对待。但我会做类似以下的事情。

    %extend Array1D
    {
        Array1D* __getitem__(PyObject *param) 
        {
            if (PySlice_Check(param))
            {
                /* Py_ssize_t might be needed here instead of ints */
                int len = 0, start = 0, stop = 0, step = 0, slicelength = 0;
    
                len = this->size(); /* Or however you get the size of a vector */
    
                PySlice_GetIndicesEx((PySliceObject*)param, len, &start, &stop, &step, &slicelength);
    
                /* Here do stuff in order to return an Array1D that is the proper slice
                   given the start/stop/step defined above */
            }
    
            /* Unexpected parameter, probably should throw an exception here */
        }
    }
    

    【讨论】:

    • 谢谢!我尝试了以下方法,但不确定该怎么做: }``
    • 我添加了一些代码,这是我会尝试的。但是有一个问题,如果 int 被视为 PyObjects,那么例如在执行 a[3] 时会调用此方法,但是您需要为此使用不同的返回类型,我不确定如何解决该问题。但是,如果 int 不像 PyObjects 那样对待,那么您应该能够定义两个 getitem 函数,一个返回 Array1D*,另一个返回 double。
    • 这太棒了!它有效,但我不得不将int 更改为Py_ssize_t。另外,(PySliceObject*)param 是做什么的?我是 C 新手,不熟悉这种表示法。
    • 这是一个类型转换。所以我们的参数是指向PyObject 类型对象的指针,但PySlice_GetIndicesEx() 将指向PySliceObject 的指针作为第一个参数。所以首先我通过调用PySlice_Check() 来检查参数是否真的是PySliceObject。由于我现在知道它是 PySliceObject,我可以告诉 c++ 将其视为使用 (PySliceObject*) 表示法的 PySliceObject 的指针。
    • 换句话说,假设您定义了几个对象。一个Cat 对象和一个继承自CatTiger 对象。您可以像这样实例化Tiger 对象Cat jerry = Tiger(); 请注意,jerry 的类型是猫,但在幕后它实际上是老虎。这是有效的,因为老虎是猫。但是如果我们需要访问 Tiger 的特定功能(比如计算条纹,因为并非所有猫都有条纹)。你需要像这样先把它施放给老虎。 int stripes = ((Tiger)jerry).stripeCount();。 * 仅表示“指向”的指针。
    猜你喜欢
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 2016-08-11
    • 2019-04-02
    相关资源
    最近更新 更多