5

使用 C API,我想创建一个包含 type 对象的 numpy 数组Quaternion,这是我用 C++ 编写的一个类。我已经有一个数组(实际上是一个std::vector),并且我想制作一个副本——或者如果可能的话使用相同的内存。

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

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

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

这基本上是这个问题的更一般的版本,没有分心。

编辑:

使用 dastrobu 的提示和我的 SWIG 包装器,我找到了一种方法。我知道不是每个人都在使用 SWIG,但对于那些使用 SWIG 的人来说,我对另一个问题的回答显示了我是如何解决的。

4

1 回答 1

3

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

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){
/* ... */
};

此外,您可以定义自己的 C-API 以PyQuaternionType允许您PyQuaternionsQuaternions

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_deallocdeallocate self->q

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

于 2013-10-23T08:56:31.223 回答