如何编写NumPy继承扩展类?

时间:2018-08-03 04:52:42

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

问题:使用C-API构造从NumPy扩展的新类时,出现分段错误。

我一直在到处搜索,试图找到这个问题的答案,但是到处都有我发现与为NumPy编写扩展模块有关的东西,它们是提供使用NumPy数组的方法的模块,这不是我所需要的。寻找。

我想知道如何为NumPy编写一个扩展类,以便它在编译时在Code中静态定义,而不是在模块导入期间生成的,例如Cython / Python所做的事情。

他们在NumPy docs上写道,新结构应采用以下形式:

typedef _new_struct {
    PyArrayObject base;
    /* new things here */
} NewArrayObject;

(首先,对于这个_new_struct实体应该是什么,我找不到任何东西。这很重要吗?)

然后,on a completely different tutorial,他们写道NumPy使用__new__而不是__init__,并且使用__finalize_array__代替__init__。

这里的问题是__new__应该负责创建新的NumPy数组并分配适当的内存,但是由于某些原因,由于我遇到了分段错误,因此似乎并非如此。

这是我的代码:

#define PY_SSIZE_T_CLEAN
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <Python.h>
#include "structmember.h"
#include "arrayobject.h"

#define PyString(s) PyUnicode_FromString(s)

typedef struct {
  PyArrayObject base;
  PyObject* name;
} NamedListObject;

static PyMemberDef NamedList_members[] = {
  {"name", T_OBJECT_EX, offsetof(NamedListObject, name), 0, "Name of the list"},
  {NULL},
};

static PyObject *
NamedList_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
  NamedListObject *self;
  self = (NamedListObject *) PyArray_Type.tp_new(type, args, kwds);
  if (self == NULL)
    return NULL;
  if (self != NULL) {
    self->name = PyString("");
    if (self->name == NULL) {
      Py_DECREF(self);
      return NULL;
    }
    Py_INCREF(self);
  }
  return (PyObject *) self;
}

static PyTypeObject
NamedListType = {
  PyVarObject_HEAD_INIT(NULL, 0)
  .tp_name = "test.NamedList",
  .tp_doc = "A named list type",
  .tp_basicsize = sizeof(NamedListObject),
  .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
  .tp_members = NamedList_members,
  .tp_new = NamedList_new,
};

static PyModuleDef
testmodule = {
  PyModuleDef_HEAD_INIT,
  .m_name = "test",
  .m_doc = "A subclassing test",
  .m_size = -1,
};

PyMODINIT_FUNC
PyInit_test(void)
{
  PyObject *module;
  import_array();
  NamedListType.tp_base = &PyArray_Type;
  if (PyType_Ready(&NamedListType) < 0)
    return NULL;

  module = PyModule_Create(&testmodule);
  if (module == NULL)
    return NULL;

  Py_INCREF(&NamedListType);
  PyModule_AddObject(module, "NamedList", (PyObject *) &NamedListType);
  return module;
}

我知道PyArray_New等方法,但是这些方法需要我准备参数。这个想法是让NumPy处理数组部分的创建,而不需要我打电话给__new __。

0 个答案:

没有答案