【问题标题】:pybind11: Python to C++ Datatype Conversion Not Workingpybind11:Python 到 C++ 数据类型转换不起作用
【发布时间】:2019-03-17 18:18:27
【问题描述】:

问题

我正在尝试转换由在 C++ 代码中调用的 python 函数返回的列表列表。尽管 pybind11 库允许从 python 数据类型到 C++ 数据类型的类型转换,但我尝试将 python 返回的列表列表转换为 C++ 字符串的 std::liststd::list,每次都失败时间。

代码

这里是python函数(该函数返回一个包含字符串值的列表):

def return_sheet(self):

     """Returns the sheet in a list of lists

     """

     dataTable = []

     for r in range(self._isheet.nrows):

         datalist = []

         for c in range(self._isheet.ncols):

             datalist.append(self._isheet.cell_value(r,c))

         dataTable.append(datalist)

 return dataTable

我在这里使用 pybind11 在 C++ 中调用它:

py::list obj = _tool.attr("return_sheet")();

data = py::cast<SheetData>(obj); // This is where the problem lies, This cast crashes the program

其中SheetDatatypedef

typedef std::list<std::list<std::string> > SheetData;

在调试的时候,我发现程序实际上在这行崩溃了:

py::object dataTable = _tool.attr("return_sheet")(); // Where _tool.attr("return_sheet")() gives an py::object which is a list of list of str

有人知道吗,我怎样才能成功地将 python 列表的列表转换为 C++ 的 std::liststd::list

编辑

这是我在 c++ 中嵌入的 python 程序文件 [xlanalysisr.py] :https://pastebin.com/gARnkMTv

这里是 c++ 代码 [main.cpp]:https://pastebin.com/wDDUB1s4

注意:xlanalysisr.py 中的所有其他函数在嵌入 c++ 时不会导致崩溃 [只有 return_sheet() 函数会导致崩溃]

【问题讨论】:

    标签: python c++ python-c-api pybind11


    【解决方案1】:

    您可以使用 Python/C API 作为解决方法(检查函数 CastToSheetData)。我包括下面的完整示例:

    程序.py

    def return_matrix():
    
        dataTable = []
        for r in range(0,2):
            datalist = []
    
            for c in range(0,2):
                datalist.append(str(r+c))
    
            dataTable.append(datalist)
        return dataTable
    

    main.cpp

    #include <pybind11/embed.h>
    #include <iostream>
    #include <list>
    #include <string>
    
    typedef std::list<std::list<std::string> > SheetData;
    
    namespace py = pybind11;
    
    SheetData CastToSheetData(PyObject *obj)
    {
        SheetData data;
        PyObject *iter = PyObject_GetIter(obj);
    
        if (!iter)
            return data;
        while (true) {
            std::list<std::string> aux_list;
            PyObject *next = PyIter_Next(iter);
            if (!next) {
                // nothing left in the iterator
                break;
            }
            PyObject *iter2 = PyObject_GetIter(next);
            if (!iter2)
                continue;
            while(true) {
                PyObject *next2 = PyIter_Next(iter2);
                if (!next2) {
                    // nothing left in the iterator
                    break;
                }
                PyObject* pyStrObj = PyUnicode_AsUTF8String(next2); 
                char* zStr = PyBytes_AsString(pyStrObj); 
                std::string foo(strdup(zStr));
                aux_list.push_back(foo);
                Py_DECREF(pyStrObj);
            }
            data.push_back(aux_list);
        }
    
        return data;
    }
    
    
    int main()
    {
        py::scoped_interpreter guard{};
        py::module calc = py::module::import("program");
        py::object result = calc.attr("return_matrix")();
    
        SheetData data = CastToSheetData(result.ptr());
    
        for (auto l : data)
        {
            std::cout << "[ ";
            for(auto s : l)
                std::cout << s <<  " ";
            std::cout << "]" << std::endl;
        }
    
        return 0;
    }
    

    输出:

    [ 0 1 ]
    [ 1 2 ]
    

    可能,最好的方法是使用load 方法内的CastToSheetData 函数中的代码来自定义type_caster

    【讨论】:

    • 感谢您帮助我,但提供的解决方案不起作用。您的代码在导入模块 [ py::module calc = py::module::import("program"); ] 在主函数中。而在我的代码中,程序在从 python 函数'return sheet' [ py::object dataTable = _tool.attr("return_sheet")(); ] .你能帮忙弄清楚吗?
    • 我没有崩溃。看起来您的问题与数据类型转换无关,而是与将 python 函数嵌入到 C++ 中有关。您能否发布您的完整代码以检查您如何导入模块_tool
    • 您是否将我的 python 代码添加到与 main.cpp 位于同一文件夹中的 program.py 文件中?
    • 当然,我确实将您的 python 程序添加到了正确的位置。?。我正在为项目使用带有 MSVC 32 位的 Qt 5.12.1。我将把我的 c++ 和 python 代码发布到我的问题描述的末尾。感谢您抽出时间帮助我。
    • 您的代码在我的电脑上运行良好。我打印了一个excel没有问题。我正在使用 64 位(我将 pybind11 编译为 64 位)。更详细一点,我使用 VSCode 和 CMake 2.8,MSVC 19.12.25835.0 64 位,我的 python 版本是 3.7 和 pybind11 v2.3dev0。别担心,我喜欢这样做哈哈
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-30
    • 2021-07-30
    • 1970-01-01
    • 2020-02-29
    • 2019-04-13
    • 2013-08-11
    • 1970-01-01
    相关资源
    最近更新 更多