我想使用 C API 创建一个包含 Quaternion
类型对象的 numpy 数组,这是我用 C++ 编写的类。我已经有了一个数组(实际上是一个 std::vector
),我想制作一个副本——或者如果可能的话使用相同的内存。
因为这不是基本类型,我需要使用 Py_Object
类型,不能使用 PyArray_SimpleNew
或任何类似的简单类型。
我猜我可能想使用 PyArray_NewFromDescr
甚至 PyArray_SimpleNewFromDescr
,但我完全不知道如何创建 PyArray_Descr
对象我需要描述我的四元数类。
谁能给我一些关于如何制作 descr 对象的建议?或者让我更好地了解如何构建我的 numpy 数组?
这基本上是 this question 的更通用版本,没有干扰。
编辑:
使用 dastrobu 的提示和我的 SWIG 包装器,我找到了一种方法来做到这一点。我知道不是每个人都在使用 SWIG,但对于那些正在使用的人,my answer on my other question展示了我是如何解决的。
最佳答案
因为 Quaternion
不是直接的数字类型,你的数组必须有 numpy.object
作为 dtype
。因此,您可以使用 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 数组= numpy.object
。
关于python - 使用 C API 创建自定义类对象的 numpy 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19532871/