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

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.

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& v) {

Py_ssize_t size = v.size();

PyArrayObject* list = (PyArrayObject*) PyList_New(size);

for(Py_ssize_t i=0; i

PyObject* o = (PyObject*) new Quaternion(v[i]);

PyList_SET_ITEM((PyObject*)list, i, o);

}

return PyArray_Return(list);

}

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.

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

解决方案

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.

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(PyArray_SimpleNew(1, &size, NPY_OBJECT));

PyObject** data = static_cast(PyArray_DATA(npy_arr));

for(npy_intp i=0; 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);

}

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值