很多时候我们需要在C++中调用python, 例如调用tensorflow 的一些优化函数,深度学习的模型等等,基本的使用方法如下(当然,要先配置好调用python 的环境。)
#include "stdafx.h"
#include<iostream>
#include <string.h>
#include <string>
#include "python.h"
using namespace std;
int main()
{
初始化Python环境
Py_Initialize();
PyRun_SimpleString("import sys");
//加入python文件路径
PyRun_SimpleString("sys.path.append('C:/Users/admin/Desktop/Test')");
//导入模块(Insert.py)
PyObject* pModule = PyImport_ImportModule("Insert");
if (!pModule)
{
cout << "Python get module failed." << endl;
return 0;
}
cout << "Python get module succeed." << endl;
//获取Insert模块内_add函数
PyObject* pv = PyObject_GetAttrString(pModule, "_add");
if (!pv || !PyCallable_Check(pv))
{
cout << "Can't find funftion (_add)" << endl;
return 0;
}
cout << "Get function (_add) succeed." << endl;
//初始化要传入的参数,args配置成传入两个参数的模式
PyObject* args = PyTuple_New(2);
//将Long型数据转换成Python可接收的类型
PyObject* arg1 = PyLong_FromLong(4);
PyObject* arg2 = PyLong_FromLong(3);
//将arg1配置为arg带入的第一个参数
PyTuple_SetItem(args, 0, arg1);
//将arg1配置为arg带入的第二个参数
PyTuple_SetItem(args, 1, arg2);
//传入参数调用函数,并获取返回值
PyObject* pRet = PyObject_CallObject(pv, args);
if (pRet)
{
//将返回值转换成long型
long result = PyLong_AsLong(pRet);
cout << "result:" << result;
}
Py_Finalize();
return 0;
}
其中 Insert.py 内容如下:
def _add(x, y):
print('add', x, 'and', y)
return x + y
1. C++ 中调用的*.py文件的路径
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('你的python文件所在路径')");
注意“你的python文件所在路径”中只能用 ‘/ ’而不能用“ \\”,否则找不到文件。正确的例子如下
PyRun_SimpleString("sys.path.append('D:/workspace')");
2. python 文件中的相对路径问题
如果C++调用的 *.py 中包含了其所在文件夹下的其他需要load 的文件,此时的相对路径不能是 *.py所在的文件,而应该是C++ 工程所在的目录,所以推荐使用绝对路径。例如:
#当被调用的*.py文件在D:/workspace 文件夹下,而C++工程不在该目录下时,需要读取test.txt最好使用以下代码。
data=np.loadtxt("D:/workspace/test.txt")
#而不用用
data=np.loadtxt("./test.txt")
3. 返回值是List时,如何读取
假设返回值是float data[43][3], 读取结果的代码如下:
//传入参数调用函数,并获取返回值
PyObject* pRet = PyObject_CallObject(pv, nullptr);
float data[34][3] = { 0 };
if (PyList_Check(pRet)) { //检查是否为List对象
int SizeOfList = PyList_Size(pRet);//List对象的大小,这里SizeOfList = 3
for (int Index_i = 0; Index_i < SizeOfList; Index_i++) {
PyObject * ListItem = PyList_GetItem(pRet, Index_i);//遍历List对象中子元素中的每个元素
int NumOfItems = PyList_Size(ListItem);
for (int Index_k = 0; Index_k < NumOfItems; Index_k++) {
PyObject *Item = PyList_GetItem(ListItem, Index_k);
cout << PyFloat_AsDouble(Item) << " ";
data[Index_i][Index_k] = PyFloat_AsDouble(Item);
Py_DECREF(Item);
}
Py_DECREF(ListItem); //释放空间
}
cout << endl;
}
else
{
cout << "Not a List" << endl;
}
其他更多类型的返回值见参考[1]
4. 参考
[1]https://blog.youkuaiyun.com/stu_csdn/article/details/69488385