从 C++ 修改 python 列表
Posted
技术标签:
【中文标题】从 C++ 修改 python 列表【英文标题】:modify a python list from C++ 【发布时间】:2013-04-05 12:15:05 【问题描述】:我有一个 Python 列表,我可以获取它的指针并将这个指针地址传递给 C++ 来处理
MyPointer = TheList.as_pointer()
现在我使用 ctypes 将此地址传递给 C++
在 C++ 中,我可以执行以下操作:
*(float*) MyPointer = 2.0f; //for example
并且 Python 值会立即更新,现在的问题是:
如何扩展或删除一些值(如直接从 C++ 修改列表)
因为我感觉这些数据是 std::vector
如何做 push_back
等等以快速方式调整大小(因为在 Python 中迭代非常慢)
【问题讨论】:
as_pointer
似乎是 Blender 特定的,据我所见……无论如何,Python list
not 实现为 std::vector
,它是一个自己的数据结构体。您需要将指针转换为该数据类型才能使用它。类型在Python C API中定义。
当您想使用 Python C-API 时,最好实际编写 C 扩展模块而不是使用 ctypes,请参阅 docs.python.org/2.7/extending/index.html 和 docs.python.org/2.7/c-api/list.html
@KonradRudolph 确实来自 Blender Python api :)
如果您需要快速迭代,您可能希望使用array.array('d')
或numpy.array
。它们允许将浮点数有效地打包到数组中。另一方面,Python 列表包含(在 C++ 术语中)指向堆栈分配对象的指针,每个对象都包含一个双精度。 IE。这就像一个std::vector<PyObject*>
,其中每个PyObject*
必须被取消引用才能到达底层double
。要将单个数字附加到 Python 列表中,您必须对其进行堆分配以获取 PyObject*
。
【参考方案1】:
仅给定该指针,您无法扩展列表。您传递给 C++ 的是内部用于实现 Python 列表的 array 的地址。这不能是std::vector
,因为 Python 列表不是作为 STL 向量实现的,而是作为 Python 对象引用的 C 级数组实现的。这些数组不包含指向 Python 列表对象的反向指针。
要更改列表,请查看the documentation 并将您的 C++ 代码与 Python 库链接。如果您确实必须从 ctypes 调用您的 C++ 函数,请使用列表的 id
调用它以获取指向列表的指针,而不是其元素数组。然后就可以像这样对列表进行操作:
#include <Python.h>
extern "C"
void append_to_list(uintptr_t lst_id)
PyObject* lst = reinterpret_cast<PyObject*>(ptr);
PyObject* new_num = PyFloat_FromDouble(2.0);
if (!new_num)
... PyFloat creation failed ...
int ret = PyList_Append(lst, new_num);
Py_DECREF(new_num);
if (ret)
... PyList_Append failed ...
【讨论】:
我理解这个概念,但是在 python 中执行时它给了我一个内存错误:在 0x000 读取访问冲突 PyList_Append 失败 没有进行错误检查,但是在每一行之后做了 printf 并且在 PyList_Append 之后没有打印 好吧,我没有检查值(但我知道错误是否会从 python 文档中生成 -1),因为我找到了一种在没有 PyObjects 的情况下工作的更好方法(我讨厌它们:D)一个浮点指针并使用它 ^_^ 仍然会尝试修改它的大小(还不知道如何)以上是关于从 C++ 修改 python 列表的主要内容,如果未能解决你的问题,请参考以下文章
使用 c++ boost::python 从 python 函数返回的列表中获取数据?