C++中如何只加载一次python脚本,然后可以调用python,只为减少时间
在 C++ 中只加载一次 Python 脚本,然后多次调用 Python 函数,可以通过使用 Python/C API 来实现。这种方法不仅可以减少每次调用 Python 函数时的开销,还能使得 Python 脚本中的状态保持一致。
下面是一个详细的示例,展示如何在 C++ 中加载一次 Python 脚本并多次调用 Python 函数。
步骤
- 初始化 Python 解释器:使用
Py_Initialize()
函数。 - 加载 Python 脚本:使用
PyRun_SimpleString()
函数或PyObject
系列函数。 - 获取 Python 函数:使用
PyObject_GetAttrString()
函数。 - 调用 Python 函数:使用
PyObject_CallObject()
函数。 - 清理资源:在程序结束时调用
Py_Finalize()
释放资源。
示例代码
假设有一个名为 script.py
的 Python 脚本,内容如下:
python# script.py
def add(a, b):
return a + b
def multiply(a, b):
return a * b
下面是 C++ 代码示例,展示如何只加载一次 script.py
脚本,然后多次调用其中的 add
和 multiply
函数。
cpp#include <Python.h>
#include <iostream>
// 初始化 Python 解释器
void initializePython() {
Py_Initialize();
}
// 加载 Python 脚本并获取模块和函数对象
PyObject* loadPythonScript(const char* script_name, const char* func_name) {
// 加载 Python 文件名(不带 .py 后缀)
PyObject* pName = PyUnicode_DecodeFSDefault(script_name);
if (!pName) {
PyErr_Print();
std::cerr << "Error: unable to decode script name" << std::endl;
return nullptr;
}
// 导入模块
PyObject* pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (!pModule) {
PyErr_Print();
std::cerr << "Error: unable to import module" << std::endl;
return nullptr;
}
// 获取函数对象
PyObject* pFunc = PyObject_GetAttrString(pModule, func_name);
if (!pFunc || !PyCallable_Check(pFunc)) {
if (PyErr_Occurred()) PyErr_Print();
std::cerr << "Error: function not found or not callable" << std::endl;
Py_XDECREF(pFunc);
Py_DECREF(pModule);
return nullptr;
}
// 函数对象引用计数+1,返回函数对象
Py_INCREF(pFunc);
Py_DECREF(pModule); // 释放模块引用
return pFunc;
}
// 调用 Python 函数
PyObject* callPythonFunction(PyObject* pFunc, int a, int b) {
PyObject* pArgs = PyTuple_Pack(2, PyLong_FromLong(a), PyLong_FromLong(b));
PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs); // 释放参数元组引用
if (!pValue) {
PyErr_Print();
std::cerr << "Error: function call failed" << std::endl;
return nullptr;
}
return pValue;
}
// 结束 Python 解释器
void finalizePython() {
Py_Finalize();
}
int main() {
// 初始化 Python 解释器
initializePython();
// 加载 Python 脚本中的函数
PyObject* pAddFunc = loadPythonScript("script", "add");
PyObject* pMultiplyFunc = loadPythonScript("script", "multiply");
if (!pAddFunc || !pMultiplyFunc) {
std::cerr << "Error: could not load Python functions" << std::endl;
finalizePython();
return 1;
}
// 调用 Python 函数
PyObject* pResult = callPythonFunction(pAddFunc, 2, 3);
if (pResult) {
std::cout << "Add result: " << PyLong_AsLong(pResult) << std::endl;
Py_DECREF(pResult); // 释放结果对象引用
}
pResult = callPythonFunction(pMultiplyFunc, 2, 3);
if (pResult) {
std::cout << "Multiply result: " << PyLong_AsLong(pResult) << std::endl;
Py_DECREF(pResult); // 释放结果对象引用
}
// 释放函数对象引用
Py_DECREF(pAddFunc);
Py_DECREF(pMultiplyFunc);
// 结束 Python 解释器
finalizePython();
return 0;
}
代码解释
初始化 Python 解释器:
cppvoid initializePython() { Py_Initialize(); }
加载 Python 脚本并获取模块和函数对象:
cppPyObject* loadPythonScript(const char* script_name, const char* func_name) { PyObject* pName = PyUnicode_DecodeFSDefault(script_name); PyObject* pModule = PyImport_Import(pName); Py_DECREF(pName); PyObject* pFunc = PyObject_GetAttrString(pModule, func_name); if (!pFunc || !PyCallable_Check(pFunc)) { PyErr_Print(); Py_XDECREF(pFunc); Py_DECREF(pModule); return nullptr; } Py_INCREF(pFunc); Py_DECREF(pModule); return pFunc; }
调用 Python 函数:
cppPyObject* callPythonFunction(PyObject* pFunc, int a, int b) { PyObject* pArgs = PyTuple_Pack(2, PyLong_FromLong(a), PyLong_FromLong(b)); PyObject* pValue = PyObject_CallObject(pFunc, pArgs); Py_DECREF(pArgs); if (!pValue) { PyErr_Print(); return nullptr; } return pValue; }
结束 Python 解释器:
cppvoid finalizePython() { Py_Finalize(); }
在
main
函数中:- 初始化 Python 解释器。
- 加载 Python 脚本中的
add
和multiply
函数。 - 调用 Python 函数并输出结果。
- 释放 Python 函数对象和解释器资源。
这种方法通过一次加载 Python 脚本,并多次调用其中的函数,有效地减少了每次调用的开销。