如何将 3D Python 列表传递给 C++ 程序
Posted
技术标签:
【中文标题】如何将 3D Python 列表传递给 C++ 程序【英文标题】:How can I pass a 3D Python list to a c++ program 【发布时间】: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
我已经看到了一些关于这个主题的问题,here 和 here
问题是其中一个问题有一个我完全看不懂的答案,而第二个只是关于返回的浮点数,我需要一个3D矢量,我在这里没有找到我需要的东西
另外,这个tutorial 没有解释如何传递一个 3d 列表,甚至根本没有一个列表。
【问题讨论】:
是否允许作弊并将 Python 数组输出视为 JSON? @Botje 是的,我可以做任何事情。但如果可能的话,最好避免这种情况,因为我对 JSON 一无所知。 有点hacky,但你可以将脚本输出到文件中,然后C++可以读取文件并从中创建向量。一行将是您的一对数字中的一个。或者您可以输出某种格式(提到了 JSON,但也可以使用其他格式)。 【参考方案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
【讨论】:
以上是关于如何将 3D Python 列表传递给 C++ 程序的主要内容,如果未能解决你的问题,请参考以下文章