我需要通过 python C API 创建一个新列表,其中包含我编写的(C++ 中)Quaternion 类对象的新副本。 [实际上,I'd really like a numpy array ,但任何顺序都可以。] 但是我尝试过的所有操作都遇到段错误。我对指针很糟糕,所以这并不奇怪。我在想,也许我需要让 python 拥有我用 new 创建的对象。
我迄今为止获得的最好成绩如下所示。我不应该在 new 时复制构建四元数吗?我在做其他愚蠢的事情吗?我现在需要告诉 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 文件,发现它是我会怎么写它。]
请您参考如下方法:
现在我看到了,这是显而易见的。我不能将任意类型转换为 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...
无论如何,我希望将来能对其他人有所帮助。
