背景
最近在使用python进行项目调研,但是代码不方便让大家体验使用,同时组内有已经用C++写好的服务框架,为了快速出demo,因此采用C++调用python代码的方式快速实现demo效果,方便展示。
但是在执行过程中,遇到了很多问题,查了很多资料,终于搞定了,下面详细介绍一下C++在调python3.6时,所需要的操作。
C++文件
头文件
include "Python.h"
初始化
Py_Initialize()
if (!Py_IsInitialized()) {
cout << "init python enev failed!" << endl;
return -1;
}
执行python指令
//PyRun_SimpleString函数执行一段python指令
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./pys/')")
//pys中存放python代码,注意代码路径,最好写绝对地址,否则可执行文件与pys必须在同一目录,来回拷贝会比较麻烦。
//python代码中若涉及到读文件操作,最好也是绝对地址,否则极易读文件失败
读取python文件
//PyImport_ImportModule
PyObject *m_pModule_ = PyImport_ImportModule("python_file");//python_file.py
if (!m_pModule_) {
cout << "can't find python_file.py" << endl;
return -1;
}
获取函数列表
PyObject *m_pDict_ = PyModule_GetDict(m_pModule_);
if (!m_pDict_) {
cout << "can't get dict!" << endl;
return -1;
}
执行函数
PyObject *pFunc = PyDict_GetItemString(m_pDict_, "init");
if (!pFunc) {
cout << "get init from python_file failed!" << endl;
return -1;
}
//传参
string conf = "conf";
PyObject *pArgs = NULL;
pArgs = PyTuple_New(2);
PyTuple_SetItem(pArgs, 0, PyUnicode_FromString(conf.c_str());//传string参数 Py_BuildValue("s", conf.c_str())也可
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 2));//传int参数
//函数调用,获取返回值
PyObject *pReturn = PyEval_CallObject(m_pMiddleFunc_, pArgs);
if (!pReturn) {
cout << "get pReturn failed!" << endl;
return -1;
}
//返回值解析
char *c1;
char *c2;
int n;
PyArg_ParseTuple(pReturn, "s|s|i", &c1, &c2, &n);
注意事项
-同一个函数的PyObject对象,全局只能获取一次,释放一次,否则会出现错误。
-若出现获取python返回值为空的情况,注意检查python代码本身是否有问题。
-代码中所有PyObject声明的对象,都需要释放。
-注意代码中文件读取时路径问题。