网站菜单

C++运行Python脚本

在C++中调用Python代码,可以使用Python的C API或第三方库如 pybind11。这里我将介绍使用Python的C API来完成你的需求。首先,你需要确保C++环境已经配置好Python的头文件和库。

准备步骤

确保已安装Python开发环境:在Linux下需要安装Python开发头文件:

sudo apt-get install python3-dev

若为交叉编译,则应安装交叉编译的python包

封装Python代码

将Python代码放入 main 函数中

你需要将给定的Python代码包装在一个函数中:

# your_python_script.py

import cv2
import time
from rknnpool import rknnPoolExecutor
from func import myFunc

def main():
    cap = "./sample.jpg"
    modelPath = "./sample"
    ret = 1
    TPEs = 4
    pool = rknnPoolExecutor(
        rknnModel=modelPath,
        TPEs=TPEs,
        func=myFunc)

    if (1):
        for i in range(1):
            frame = cv2.imread(cap)
            if not ret:
                cap.release()
                del pool
                exit(-1)
            pool.put(frame)

    frames, loopTime, initTime = 0, time.time(), time.time()

    while(True):
        frames += 1
        frame = cv2.imread(cap)
        pool.put(frame)
        frame, flag = pool.get()
        if flag == False:
            break
        cv2.imshow('yolov5', frame)
        
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
        if frames % 30 == 0:
            print("30帧平均帧率:\t", 30 / (time.time() - loopTime), "帧")
            loopTime = time.time()

    print("总平均帧率\t", frames / (time.time() - initTime))
    cap.release()
    cv2.destroyAllWindows()
    pool.release()

C++代码实例

#include <Python.h>
#include <iostream>

int main() {
    // 初始化Python解释器
    Py_Initialize();

    // 将当前目录添加到Python模块的搜索路径中
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')"); // 确保你的Python文件所在目录被包含

    // 导入你的Python模块
    PyObject* pName = PyUnicode_DecodeFSDefault("your_python_script"); // Python脚本文件名(不带.py)
    PyObject* pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != nullptr) {
        // 调用Python代码
        PyObject* pFunc = PyObject_GetAttrString(pModule, "main"); // 假设你的Python脚本中有一个`main`函数
        if (PyCallable_Check(pFunc)) {
            PyObject* pValue = PyObject_CallObject(pFunc, nullptr);
            if (pValue != nullptr) {
                std::cout << "Python function executed successfully!" << std::endl;
                Py_DECREF(pValue);
            } else {
                PyErr_Print();
            }
        } else {
            if (PyErr_Occurred()) PyErr_Print();
            std::cerr << "Cannot find function 'main'" << std::endl;
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    } else {
        PyErr_Print();
        std::cerr << "Failed to load the Python script" << std::endl;
    }

    // 结束Python解释器
    Py_Finalize();

    return 0;
}

关键步骤说明

  • 将你的Python代码保存到一个脚本文件中,例如 your_python_script.py
  • 确保 your_python_script.py 中包含一个可调用的 main() 函数来执行你提供的代码。
  • 通过 Py_Initialize() 初始化Python解释器,通过 Py_Finalize() 结束Python解释器。
  • PyObject* pValue = PyObject_CallObject(pFunc, nullptr);会返回Python程序中对应函数的返回值,后续对齐进行处理,通过PyObject_GetAttrString等方式转换成C++支持的格式。

额外说明

若Python程序中导入了类似cv2与rknn等第三方库,运行时可能会出现module not found的问题。此时需要使用 PyRun_SimpleString(“sys.path.append(‘/path/to/your/python/site-packages’)”);加载对应库的路径

#rknnlite的路径可以通过
python3 -c "import rknnlite; print(rknnlite.__file__)"查询
#cv2的路径可以通过
python3 -c "import cv2; print(cv2.__file__)"查询
显示评论 (0)

文章评论

相关推荐

Yolov5_Seg输出解析

通过矩阵乘法(在代码中称为“matmul”)来计算分割掩码的原因,主要与实例分割网络(例如 YOLOv5 Segmentation)的实现方式有关。这种方法实际上是一种高效的特征图与目标分割系数组合的…

Ubuntu交叉编译Python

在 Ubuntu 上交叉编译 Python 的流程通常用于为不同平台生成可执行文件(如 ARM、MIPS 等)。以下是一般的操作步骤: 1. 安装必要的依赖工具 首先,确保已经安装了编译所需的工具和依…