【问题标题】:Creating a numpy array of custom-class objects with C API使用 C API 创建一个自定义类对象的 numpy 数组
【发布时间】:2013-10-23 04:34:49
【问题描述】:

使用 C API,我想创建一个包含 Quaternion 类型对象的 numpy 数组,这是我用 C++ 编写的一个类。我已经有一个数组(实际上是std::vector),我想复制一份——或者尽可能使用相同的内存。

由于这不是基本类型,我需要使用Py_Object 类型,并且不能使用PyArray_SimpleNew 或类似的简单类型。

我猜我可能想使用PyArray_NewFromDescr 甚至PyArray_SimpleNewFromDescr,但我完全不知道如何创建我需要描述我的四元数类的PyArray_Descr 对象。

谁能给我一些关于如何制作descr对象的指示?或者让我更好地了解如何构建我的 numpy 数组?

这基本上是this question 的更通用版本,没有分心。

编辑:

使用 dastrobu 的提示和我的 SWIG 包装器,我找到了一种方法。我知道并不是每个人都在使用 SWIG,但对于那些使用 SWIG 的人来说,my answer on my other question 展示了我是如何解决它的。

【问题讨论】:

    标签: python numpy python-c-api python-c-extension


    【解决方案1】:

    由于Quaternion 不是直接数字类型,因此您的数组必须具有numpy.objectdtype。因此,您可以使用PyArray_SimpleNew(..., NPY_OBJECT) 创建一个数组并填写数据。 问题是您的 Quaternion 类不是 python 类型。所以用Quaternion 类型的对象的引用填充数组是行不通的。 (在这种情况下,如果您从填充了 python 的四元数的数组中提取一个元素,您希望发生什么?) 相反,您需要用PyQuaternion 之类的东西包装Quaternion 类。包装器负责引用计数和内存管理。它看起来像:

    typedef struct {
        PyObject_HEAD
        Quaternion *q;
    }PyQuaternion;
    
    static PyTypeObject PyQuaternion_Type = {
        PyObject_HEAD_INIT(NULL)
        0,                                        /*ob_size*/
        "Quaternion",                             /*tp_name*/
        sizeof(PyQuaternion),                     /*tp_basicsize*/
    /* ... */
    };
    
    
    static PyObject *
    PyQuaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds){
    /* ... */
    };
    
    static int 
    PyQuaternion_init(PyQuaternion *self, PyObject *args, PyObject *kwds){
    /* ... */
    };
    
    static void PyQuaternion_dealloc(PyQuaternion *self){
    /* ... */
    };
    

    此外,您可以为 PyQuaternionType 定义自己的 C-API,从而允许您从 Quaternions 创建 PyQuaternions

    static PyObject *
    PyQuaternion_New(Quaternion *q){
        PyQuaternion *self;
        self = (PyQuaternion *)PyQuaternion_Type.tp_new(type, NULL, NULL);
        self->q = q; 
        return (PyObject *)self;
    }
    

    请注意self->q 将由PyQuaternion_dealloc 函数处理,因此请考虑内存管理。最简单的方法是将所有权传递给包装器并让PyQuaternion_dealloc 释放self->q

    PyQuaternion_New 函数允许您包装Quaternion 对象并将它们填充到任何python 容器中,例如列表、元组,当然还有带有dtype = numpy.object 的numpy 数组。

    【讨论】:

    • 谢谢。这很有意义。我实际上是通过 SWIG 完成这一切的,所以我确信它为我包装了四元数作为某种类型的 PyObject。现在我只需要弄清楚如何使用它......
    猜你喜欢
    • 1970-01-01
    • 2018-01-09
    • 2018-01-25
    • 2014-06-20
    • 1970-01-01
    • 2015-05-15
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多