pybind11 返回 numpy 对象数组

Posted

技术标签:

【中文标题】pybind11 返回 numpy 对象数组【英文标题】:pybind11 return numpy array of objects 【发布时间】:2017-07-16 03:30:34 【问题描述】:

使用 pybind11 C++ API 和 python3,我们如何在 C++ 实现中正确地创建一个 numpy 对象数组(即 unicode 字符串)并将其返回给 python?传递给 pybind11::array() 的底层数据数组的确切内存布局是什么?我们究竟需要如何管理内存,即删除/释放?

请注意,这是必要的,因为我们希望在创建 pandas DataFrame 时将该字符串数组与其他 POD 数组结合使用。

【问题讨论】:

我对@9​​87654321@ 无能为力。但是numpy 数组可以使用numpy C API 函数创建。数组布局基本相同,属性加数据缓冲区。对于对象类型,数据缓冲区包含指向内存中其他位置的对象的指针。使用unicode dtype,缓冲区实际上包含字符串(填充到指定长度)。您可能需要学习 numpy 文档。 谢谢 - 似乎最好的方法是手动创建带有对象的缓冲区,然后弄清楚 pybind11 如何管理与底层数组以及所有对象关联的内存... 【参考方案1】:

事实证明有必要:

    创建一个 PyObject 指针数组,填充数组,即

    auto* pbuf = new PyObject*[arraySize]; // or create via pybind11 API...
    pbuf[0] = <new object...>
    pbuf[1] = <new object...>
    etc.
    

    创建一个带有胶囊的“对象” py::array():

    py::capsule freeWhenDone(pbuf, [](void* pp) 
            delete [] (PyObject*)pp; // or else properly free the pbuf memory
        );
    
    arr = py::array(py::dtype("object"),
        shape, strides, pbuf, freeWhenDone);
    

【讨论】:

您还知道不需要freeWhenDone 的解决方案吗?我想如果内存被 pybind11 malloc'd,py::array 可以使用正常的 free'ing。 我能够让它工作而不泄漏的方法是使用胶囊。此外,当内部对象是 python 字符串时,我必须释放每个单独分配的对象。更新版本的pybind11可能还有其他解决方案。

以上是关于pybind11 返回 numpy 对象数组的主要内容,如果未能解决你的问题,请参考以下文章

Pybind11 默认参数 numpy 数组或无

使用 carma(犰狳矩阵和 numpy 数组)用 pybind11 包装 c++ 类时出错

Pybind11:外部类型作为返回值

pybind11 保持对象活着

将 std::vector 作为 numpy 数组返回给 python

如何使用 pybind 传递 numpy 数组列表