python - 将 C++ 缓冲区复制到 Python 的最佳方法

标签 python c++ c

在使用 Python 处理 C 扩展时,将数据从 C++ 数组或 vector 移动到 PyObject/PyList 的最佳方法是什么> 所以它可以返回给 Python?

我现在使用的方法似乎有点笨拙。我遍历每个元素并调用 Py_BuildValue 将值附加到 PyList

有没有类似memcpy的东西?

最佳答案

如果您的 vector 包含同质数值数据,那么您最好创建一个 array.array将值传输到 Python。

与列表不同,数组在内部将其值存储为原生 C 值的连续数组,但在其他方面提供了一个类似 Pythonic 列表的接口(interface)。它使用最大限度地减少内存占用,并使您能够实际使用单个 memcpy 调用来有效地传输数据。这是一个例子:

PyObject *
vec_to_array(std::vector<double>& vec)
{
    static PyObject *single_array;
    if (!single_array) {
        PyObject *array_module = PyImport_ImportModule("array");
        if (!array_module)
            return NULL;
        PyObject *array_type = PyObject_GetAttrString(array_module, "array");
        Py_DECREF(array_module);
        if (!array_type)
            return NULL;
        // array.array('d', [0.0])
        single_array = PyObject_CallFunction(array_type, "c[d]", 'd', 0.0);
        Py_DECREF(array_type);
        if (!single_array)
            return NULL;
    }

    // extra-fast way to create an empty array of count elements:
    //   array = single_element_array * count
    PyObject *pysize = PyLong_FromSsize_t(vec.size());
    if (!pysize)
        return NULL;
    PyObject *array = PyNumber_Multiply(single_array, pysize);
    Py_DECREF(pysize);
    if (!array)
        return NULL;

    // now, obtain the address of the array's buffer
    PyObject *buffer_info = PyObject_CallMethod(array, "buffer_info", "");
    if (!buffer_info) {
        Py_DECREF(array);
        return NULL;
    }
    PyObject *pyaddr = PyTuple_GetItem(buffer_info, 0);
    void *addr = PyLong_AsVoidPtr(pyaddr);

    // and, finally, copy the data.
    if (vec.size())
        memcpy(addr, &vec[0], vec.size() * sizeof(double));

    return array;
}

通过模板特化来增强它以支持其他原始类型留给读者作为练习。

关于python - 将 C++ 缓冲区复制到 Python 的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28560045/

相关文章:

python - 如何使用 any() 函数检查变量是否与列表中的任何项目匹配?

python - 我可以将views.py文件放在django的项目文件夹中吗?

python - python 中的字节串到图像

c++ - 在类中隐藏 RNG

c - LoadImage() 具有可变路径?

python - 如何迭代 SciPy 稀疏矩阵中的一行?

c++ - 尝试使用 SWIG 将 C++ 编译为 Ruby 时没有这样的文件或目录 "ruby/config.h"

用于碰撞检测的 C++ 双迭代器循环

java - 如何让Java和C程序一起通信

c - 编写一个程序求正奇数之和与小于或等于30的正偶数的乘积