使用C API创建自定义类对象的numpy数组 [英] Creating a numpy array of custom-class objects with C API

查看:94
本文介绍了使用C API创建自定义类对象的numpy数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用C API创建一个numpy数组,其中包含类型为Quaternion的对象,这是我用C ++编写的类.我已经有一个这样的数组(实际上是一个std::vector),并且我想进行复制-或在可能的情况下使用相同的内存.

Using the C API, I would like to create a numpy array containing objects of type Quaternion, which is a class I've written in C++. I already have an array of these (actually a std::vector), and I want to make a copy -- or use the same memory if possible.

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

Since this isn't a basic type, I need to use Py_Object types, and can't use PyArray_SimpleNew or anything easy like that.

我猜我可能想使用PyArray_NewFromDescr甚至PyArray_SimpleNewFromDescr,但是我完全无法理解如何创建PyArray_Descr对象,我需要描述我的Quaternion类.

I'm guessing I might want to use PyArray_NewFromDescr or even PyArray_SimpleNewFromDescr, but I am completely and utterly lost as to how I might create the PyArray_Descr object I need to describe my Quaternion class.

任何人都可以给我一些有关如何制作该descr对象的指示吗?还是让我对如何构造numpy数组有一个更好的主意?

Can anyone give me some pointers about how to make that descr object? Or give me a better idea of how to construct my numpy array?

这基本上是这个问题,没有干扰.

This is basically a more general version of this question, without the distractions.

使用dastrobu的提示以及我的SWIG包装程序,我找到了一种方法.我知道不是每个人都在使用SWIG,但是对于那些正在使用SWIG的人,我对其他问题的回答显示了我的工作方式

Using dastrobu's hint, and my SWIG wrapper, I found a way to do it. I know that not everyone is using SWIG, but for those who are, my answer on my other question shows how I worked it out.

推荐答案

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

Since Quaternion is not directly a numeric type, your array must have numpy.object as dtype. Hence, you can use PyArray_SimpleNew(..., NPY_OBJECT) to create an array and fill in the data. The problem is that your Quaternion class is not a python type. So filling the array with references to objects of type Quaternion will not work. (In this case, what would you expect to happen, if you extract an element from the array filled with quaternions from python?) Instead, you need to wrap the Quaternion class with something like PyQuaternion. The wrapper takes care of reference counts and memory management. It will look something like:

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

Furthermore you can define your own C-API for the PyQuaternionType allowing you to create PyQuaternions from Quaternions

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.

Be aware that self->q will be handled by the PyQuaternion_dealloc function, so think about the memory management. The simplest would be to pass ownership to the wrapper and let PyQuaternion_dealloc deallocate self->q.

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

The PyQuaternion_New function allows you to wrap Quaternion objects and fill them in to any python container, like lists, tuples and of course also numpy arrays with dtype = numpy.object.

这篇关于使用C API创建自定义类对象的numpy数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆