在 python C API 中返回新的自定义类对象的列表

Posted

技术标签:

【中文标题】在 python C API 中返回新的自定义类对象的列表【英文标题】:Return list of new custom-class objects in python C API 【发布时间】:2013-10-23 03:51:36 【问题描述】:

我需要通过 python C API 创建一个新列表,其中包含我编写的 Quaternion 类的对象的新副本(在 C++ 中)。 [实际上,I'd really like a numpy array,但任何形式的序列都可以。]但是我尝试过的所有事情都出现了段错误。我的指针很糟糕,所以这并不是一个大惊喜。我在想也许我需要给我用new创建的对象的python所有权。

到目前为止,我得到的最好成绩如下所示。我不应该在newing 时复制构造四元数吗?我在做其他愚蠢的事情吗?我现在需要告诉 python 它拥有引用吗?被退回的名单是否应该如我所料那样存在并过上幸福的生活?

PyObject* Objectify(std::vector<Quaternion>& v) 
  Py_ssize_t size = v.size();
  PyArrayObject* list = (PyArrayObject*) PyList_New(size);
  for(Py_ssize_t i=0; i<size; ++i) 
    PyObject* o = (PyObject*) new Quaternion(v[i]);
    PyList_SET_ITEM((PyObject*)list, i, o);
  
  return PyArray_Return(list);

我可以验证列表在返回之前是否仍然包含正确的元素。也就是说,在上面的循环之后,我创建一个新循环并在列表值旁边打印出原始值,它们匹配。该函数将返回,我可以继续使用 python。但是一旦在循环之外使用列表,就会发生段错误。

[实际上,这一切都是在 SWIG 中完成的,并且此代码位于变量名称略有不同的类型映射中,但我可以查看 _wrap.cxx 文件,发现这正是我编写的方式.]

【问题讨论】:

【参考方案1】:

现在我看到了,这很明显。我不能将任意类型转换为PyObject;它实际上需要有一些实际的 python 结构。例如,我认为 PyArrayObject 可以这样转换,但我的随机类需要被包装,正如 dastrobu 在我的 other question 中解释的那样。

正如我所提到的,我正在使用 SWIG,它已经将Quaternion 包装成某种PyObject(尽管它被赋予了其他名称来表示它是由 SWIG 制造的)。因此,虽然这通常不能回答我的问题,但以下内容正是我所需要的(包括创建 numpy 数组,而不仅仅是列表):

npy_intp size = v.size();
PyArrayObject *npy_arr = reinterpret_cast<PyArrayObject*>(PyArray_SimpleNew(1, &size, NPY_OBJECT));
PyObject** data = static_cast<PyObject**>(PyArray_DATA(npy_arr));
for(npy_intp i=0; i<size; ++i) 
  PyObject* qobj = SWIG_NewPointerObj((new Quaternions::Quaternion(v[i])),
                                      SWIGTYPE_p_Quaternions__Quaternion, SWIG_POINTER_OWN);
  if(!qobj) SWIG_fail;
  data[i] = qobj;
  Py_INCREF(qobj);

我还应该指出,我最初尝试使用PyArray_SET_ITEM 来分配此代码中列表的项目,但不断收到段错误,这就是我使用这种奇怪方法的原因。我想知道它是否与NPY_OBJECT的偏移量有关...

无论如何,我希望这对将来的其他人有所帮助。

【讨论】:

以上是关于在 python C API 中返回新的自定义类对象的列表的主要内容,如果未能解决你的问题,请参考以下文章

如何让 Laravel 返回 JSON REST API 的自定义错误

从 C/C++ 调用 python 方法,并提取其返回值

从 C/C++ 调用 python 方法,并提取其返回值

从我的自定义中间件返回到角度时,asp .net core api cors 问题

C ++在boost python中使用带有命名空间的自定义智能指针

金字塔 jsonrpc 中的自定义错误消息