C++调用python(执行py文件)的全过程

  • Post category:Python

C++调用Python(执行Python文件)的全过程可以分为以下步骤:

  1. 确定Python环境

在开始前,需要确保正确设置了Python环境变量,并且已经正确安装了所需要的Python包(例如numpy、pandas等)。

  1. 编写Python代码

在C++中调用Python时,需要事先编写好Python代码,并将其保存为.py文件。Python代码中必须定义一些函数或者类,供C++调用。例如:

# example.py
def add(a, b):
    return a + b

上述代码定义了一个名为“add”的函数,该函数可以接受两个参数,并返回它们的和。这个函数就是Python所提供给C++使用的接口。

  1. 调用Python脚本

为了从C++中调用Python,我们需要使用Python提供的API。其中,最主要的API函数是Py_Initialize和PyRun_SimpleString。

#include <Python.h>
int main() {
  // 初始化Python环境
  Py_Initialize();
  // 调用Python脚本
  PyRun_SimpleString("import example\nresult = example.add(1, 2)\nprint(result)");
  // 关闭Python环境
  Py_Finalize();
  return 0;
}

上述代码通过调用Py_Initialize函数来初始化Python环境,然后调用PyRun_SimpleString函数来执行Python脚本。在这个例子中,我们导入了例子中定义的Python模块,并调用其中的add函数,并将结果输出到标准输出流中。

  1. 嵌入Python环境

如果我们需要从C++中调用Python函数,可以通过Python提供的API函数来实现。

#include <Python.h>
int main() {
  // 初始化Python环境
  Py_Initialize();
  // 加载Python脚本
  FILE* fp = _Py_fopen("example.py", "r");
  PyRun_SimpleFile(fp, "example.py");
  fclose(fp);
  // 导入Python模块
  PyObject* pModule = PyImport_ImportModule("example");
  // 获取Python函数对象
  PyObject* pFunc = PyObject_GetAttrString(pModule, "add");
  // 设置Python函数参数
  PyObject* pArgs = PyTuple_New(2);
  PyTuple_SetItem(pArgs, 0, PyLong_FromLong(1));
  PyTuple_SetItem(pArgs, 1, PyLong_FromLong(2));
  // 调用Python函数
  PyObject* pResult = PyObject_CallObject(pFunc, pArgs);
  // 获取Python函数返回值
  int result = (int) PyLong_AsLong(pResult);
  printf("%d", result);
  // 释放Python对象
  Py_DECREF(pArgs);
  Py_DECREF(pResult);
  Py_DECREF(pFunc);
  Py_DECREF(pModule);
  // 关闭Python环境
  Py_Finalize();
  return 0;
}

上述代码通过调用PyImport_ImportModule函数导入Python模块,并通过PyObject_GetAttrString函数获取其中的add函数。然后,通过PyTuple_New和PyTuple_SetItem函数设置函数参数,并通过PyObject_CallObject函数调用add函数并获取其返回值。

示例1:计算两个数的平均值

Python代码:

# average.py
def average(a, b):
    return (a + b) / 2

C++代码:

#include <Python.h>
int main() {
  // 初始化Python环境
  Py_Initialize();
  // 加载Python脚本
  FILE* fp = _Py_fopen("average.py", "r");
  PyRun_SimpleFile(fp, "average.py");
  fclose(fp);
  // 导入Python模块
  PyObject* pModule = PyImport_ImportModule("average");
  // 获取Python函数对象
  PyObject* pFunc = PyObject_GetAttrString(pModule, "average");
  // 设置Python函数参数
  PyObject* pArgs = PyTuple_New(2);
  PyTuple_SetItem(pArgs, 0, PyLong_FromLong(1));
  PyTuple_SetItem(pArgs, 1, PyLong_FromLong(3));
  // 调用Python函数
  PyObject* pResult = PyObject_CallObject(pFunc, pArgs);
  // 获取Python函数返回值
  double result = PyFloat_AsDouble(pResult);
  printf("%f", result);
  // 释放Python对象
  Py_DECREF(pArgs);
  Py_DECREF(pResult);
  Py_DECREF(pFunc);
  Py_DECREF(pModule);
  // 关闭Python环境
  Py_Finalize();
  return 0;
}

示例2:使用Python脚本进行图像处理

Python代码:

# image.py
from PIL import Image
import os

def resize_image(file_in, file_out, size=(128, 128)):
    with Image.open(file_in) as im:
        im.thumbnail(size)
        im.save(file_out, "JPEG")
    return os.path.getsize(file_out)

C++代码:

#include <Python.h>
int main() {
  // 初始化Python环境
  Py_Initialize();
  // 加载Python脚本
  FILE* fp = _Py_fopen("image.py", "r");
  PyRun_SimpleFile(fp, "image.py");
  fclose(fp);
  // 导入Python模块
  PyObject* pModule = PyImport_ImportModule("image");
  // 获取Python函数对象
  PyObject* pFunc = PyObject_GetAttrString(pModule, "resize_image");
  // 设置Python函数参数
  PyObject* pArgs = PyTuple_New(3);
  PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", "test.jpg"));
  PyTuple_SetItem(pArgs, 1, Py_BuildValue("s", "test_sm.jpg"));
  PyTuple_SetItem(pArgs, 2, Py_BuildValue("(ii)", 128, 128));
  // 调用Python函数
  PyObject* pResult = PyObject_CallObject(pFunc, pArgs);
  // 获取Python函数返回值
  int result = (int) PyLong_AsLong(pResult);
  printf("%d", result);
  // 释放Python对象
  Py_DECREF(pArgs);
  Py_DECREF(pResult);
  Py_DECREF(pFunc);
  Py_DECREF(pModule);
  // 关闭Python环境
  Py_Finalize();
  return 0;
}

上述代码中,我们调用resize_image函数将test.jpg压缩成128×128的尺寸,并保存为test_sm.jpg。函数的返回值是压缩后的文件大小(单位为字节)。