返回python C API中新的自定义类对象的列表 [英] Return list of new custom-class objects in python C API

查看:142
本文介绍了返回python C API中新的自定义类对象的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要通过python C API创建一个新列表,其中包含我编写的(用C ++)的Quaternion类的对象的新副本. [实际上,我真的很想一个numpy数组,但任何顺序都可以.]但是我尝试的所有方法都出现了段错误.我对指针很糟糕,所以这并不奇怪.我在想,也许我需要赋予使用new创建的对象的python所有权.

I need to create a new list via the python C API containing new copies of objects of a Quaternion class I've written (in C++). [Actually, I'd really like a numpy array, but any sort of sequence would do.] But I'm getting seg faults with everything I've tried. I'm terrible with pointers, so that's not a big surprise. I'm thinking maybe I need to give python ownership of the objects I create with new.

到目前为止,我获得的最好成绩如下. new时,我不应该复制构建四元数吗?我还在做其他愚蠢的事情吗?我是否需要告诉python它现在拥有引用?如我所料,返回的清单是否应该存在并过着幸福的生活?

The best I've gotten so far appears below. Am I not supposed to copy-construct the Quaternion while newing it? Am I doing something else stupid? Do I need to tell python it owns the reference now? Should the returned list exist and live a happy life, as I expected?

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.但是一旦在循环之外使用该列表,就会发生段错误.

I can verify that the list still has the correct elements just before the return. That is, after the loop above, I make a new loop and print out the original values next to the list values, and they match. The function will return, and I can keep using python. But once the list is used outside the loop, the segfaults happen.

[实际上,这都是在SWIG中完成的,并且此代码在具有稍微不同的变量名的类型图中找到,但是我可以在_wrap.cxx文件中查找,发现这正是我编写它的方式.]

[Actually, this is all being done in SWIG, and this code is found in a typemap with slightly different variable names, but I can look in the _wrap.cxx file, and see that it's just how I would have written it.]

推荐答案

现在我明白了,这很明显.我不能只是将任意类型强制转换为PyObject;它实际上需要具有一些实际的python结构.例如,我认为PyArrayObject可以这样转换,但是我的随机类需要包装,如dastrobu在我的

Now that I see it, it's obvious. I can't just cast an arbitrary type to a PyObject; it needs to actually have some actual python structure. E.g., I'm thinking a PyArrayObject can be cast as such, but my random class needs to be wrapped, as dastrobu explained on my other question.

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

As I mentioned, I'm using SWIG, which already wraps Quaternion into some kind of PyObject (though it's given some other name to denote that it's made by SWIG). So, while this doesn't answer my question in general, the following does exactly what I need (including creating numpy arrays, rather than just lists):

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 ...

I should also point out that I originally tried using PyArray_SET_ITEM to assign the items of the list in this code, but kept getting segfaults, which is why I use this weird method. I wonder if it has something to do with the offsets of the NPY_OBJECT...

无论如何,我希望以后能对其他人有所帮助.

Anyway, I hope that helps someone else in the future.

这篇关于返回python C API中新的自定义类对象的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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