【问题标题】:How can I pass a 3D Python list to a c++ program如何将 3D Python 列表传递给 C++ 程序
【发布时间】:2021-07-29 14:16:18
【问题描述】:

我有一个 .py 文件,其中包含签名浮点数的 3d 列表。

test.py

def myfunc():
    tabToReturn = [[[-1.03,5.68],[4.16,-78.12]],[[74.1,8.95],[59.82,1.48]],[[74.1,8.95],[59.82,87.4]]]
    print(tabToReturn)
    return tabToReturn

我想调用那个 .py,让它返回这个 3d 列表,并将它转换为我的 c++ 程序的 3D 矢量。

这是一个检查我是否得到我们需要的示例:

program.cpp

#include <iostream>
std::vector<std::vector<std::vector<float>>> callPython();
int main(int argc, char** argv)
{


    std::vector<std::vector<std::vector<float>>> my3DVector = callPython();
    

    std::cout << "Result we got : "<< std::endl;

    for (int i = 0; i < my3DVector.size(); i++)
    {


        for (int j = 0; j < my3DVector[i].size(); j++)
        {

            for (int k = 0; k < my3DVector[i][j].size(); k++)
            {
                std::cout << my3DVector[i][j][k];
                std::cout << " ";

            }


        }
        std::cout << "" << std::endl;
    }
}

输出应该是:

Result we got :
-1.03 5.68
4.16 -78.12
74.1 8.95
59.82 1.48
74.1 8.95
59.82 87.4

我已经看到了一些关于这个主题的问题,herehere

问题是其中一个问题有一个我完全看不懂的答案,而第二个只是关于返回的浮点数,我需要一个3D矢量,我在这里没有找到我需要的东西

另外,这个tutorial 没有解释如何传递一个 3d 列表,甚至根本没有一个列表。

【问题讨论】:

  • 是否允许作弊并将 Python 数组输出视为 JSON?
  • @Botje 是的,我可以做任何事情。但如果可能的话,最好避免这种情况,因为我对 JSON 一无所知。
  • 有点hacky,但你可以将脚本输出到文件中,然后C++可以读取文件并从中创建向量。一行将是您的一对数字中的一个。或者您可以输出某种格式(提到了 JSON,但也可以使用其他格式)。

标签: python c++ list vector


【解决方案1】:

在 Python 方面:

json.dump(mylist, fp=open("out.json", "w"))

在 C++ 方面,使用 nlohmann::json,一个仅头文件的库:

system("python mypyfile.py");

using nlohmann::json;
std::ifstream jsonfile("out.json");
json mylist;
jsonfile >> mylist;

std::vector<std::vector<std::vector<float>>> matrix;
for (auto& dim1: mylist) {
  std::vector<std::vector<float>> dim1v;
  for (auto& dim2: dim1) {
    std::vector<float> dim2v;
    for (auto& elem: dim2) {
      dim2v.push_back(elem.get<float>());
    }
    dim1v.push_back(dim2v);
  }
  matrix.push_back(dim1v);
}

【讨论】:

    【解决方案2】:
    #creating 3d list
    
    3D_list= [[ [A,B], [C,D] ] ,[ [E,F], [G,H] ], [ [I,J],[K,L] ] ]
    
    #printing 3d list
    
    print(3D_list)
    

    【讨论】:

      【解决方案3】:

      尽管@Botje 的回答(可能)是正确的,但我得到了一个不使用 json 的解决方案。

      经过一番挣扎,我找到了C-API的来源:

      多亏了我找到了解决这个问题的解决方案,无论你的向量的维度是多少。

      详情如下:

      #include <Python.h> //first to import
      #include <iostream>
      std::vector<std::vector<std::vector<float>>> callPython()
      {
          std::cout << "Initialize the library" << std::endl;
          Py_Initialize();
      
          std::cout << "I get the python file name" << std::endl;
          PyObject* pyFile = PyUnicode_FromString((char*)"test");
      
      
          std::cout << "I import it" << std::endl;
          PyObject* myModule = PyImport_Import(pyFile);
      
          auto mdict = PyModule_GetDict(myModule);
      
      
      
          std::cout << "I get the name of the function I want to use from my python file" << std::endl;
          PyObject* myFunction = PyDict_GetItemString(mdict, "myfunc");
      
      
          std::cout << "I create the parameter I need to use" << std::endl;
          
          
          std::cout << "INFO : According to the API, we do not use PyString_ since Python 3.X anymore, but PyBytes" << std::endl;
          //----
          std::cout << "We call the function (with the appropriate parameter), we have imported and store the result in my result" << std::endl;
          auto myResult = PyObject_CallFunction(myFunction, NULL);
      
          if (!PyList_Check(myResult))
          {
              std::cout << "(!) (!) (!) THAT IS NOT A LIST (!) (!) (!)" << std::endl;
          }
      
      
          //----Getting the element givent by the python program, and store them in a 3d vector
      
          std::cout << "We iterate through the list stored in myResult and store everything in a 3D vector" << std::endl;
          //--the 3d vector we need, you must change its dimension if you work with different dimensions
          std::vector<std::vector<std::vector<float>>> my3DVector;
          //--each list in another list is a Python Object that we should extract
          
      for (Py_ssize_t i = 0; i < PyList_Size(myResult); i++)
      {
          PyObject* firstDim = PyList_GetItem(myResult, i);
      
          std::vector<std::vector<float>> secondDimCpp; 
      
          for (Py_ssize_t j = 0; j < PyList_Size(firstDim); j++)
          {
              PyObject* secondDim = PyList_GetItem(firstDim, j);
      
              std::vector<float> lastDimCpp; 
      
      
              for (Py_ssize_t k = 0; k < PyList_Size(secondDim); k++)
              {
                  PyObject* thirdDim = PyList_GetItem(secondDim, k); //we get the value of an axis
      
                  float value = PyFloat_AsDouble(thirdDim); //we convert it to a double
      
                  lastDimCpp.push_back(value); //we store it in a vector
      
              }
      
              secondDimCpp.push_back(lastDimCpp);
          }
          my3DVector->push_back(secondDimCpp);
      }
      
      
      
          return my3DVector;
      }
      

      注意:我这里是按值返回向量,效率不高,你可能更喜欢用智能指针返回

      另外,由于这是一个多维列表,我们必须使用ListObjects

      【讨论】:

        猜你喜欢
        • 2023-03-28
        • 2021-11-03
        • 1970-01-01
        • 2016-11-08
        • 2015-03-07
        • 1970-01-01
        • 1970-01-01
        • 2019-08-30
        相关资源
        最近更新 更多