C++嵌入python

序言
参数说明
代码

## 序言
上篇介绍了Qt中调用python相关注意事项,这篇着重介绍C++(Qt)如何嵌入python,并且使用python中函数或者类。注意使用头文件声明python.h, 以及对应的python.lib

## 参数说明

一、初始化
Py_Initialize()
python模块初始化操作。

二、结束收尾
Py_Finalize()
释放相关模块操作。

三、导入模块
PyImport_ImportModule()
python一个文件其实就是一个模块,导入所需要的文件名即可前提是python搜索路径中有。
qt调用python模块时,比如说myDemo.py ,它会查找目录如下
程序的根目录
PYTHONPATH环境变量设置的目录
标准库的目录
任何能够找到的.pth文件的内容
第三方扩展的site-package目录
优先去 D:\Python\Python37-32安装系统目录下或者其他库目录下去找py文件 如果找不到,再去有路径pth内容搜索。

四、返回模块里函数
PyObject_GetAttrString()
返回模块里面的函数.

五、传递参数给python
Py_BuildValue()

建立一个参数元组,一般都是用这个函数来建立元组,然后将这个元组作为参数传递给python里面的函数。

六、调用函数
PyEval_CallObject()

调用函数,并把“Py_BuildValue”建立的元组作为参数传递给被调用的函数。

七、返回python的结果
PyArg_Parse()

将python调用的结果返回。

## 代码

python

import matplotlib.pyplot as plt
import numpy as np
import multiprocessing

def getPic(str):
    print ('enter getPic...', str)
    x = np.arange(9)
    y = np.sin(x)
    z = np.cos(x)
    print ('enter getPic...')
    plt.plot(x, y, marker="*", linewidth=3, linestyle="--", color="orange")
    plt.plot(x, z)
    plt.title("matplotlib")
    plt.xlabel("height")
    plt.ylabel("width")
    plt.legend(["Y","Z"], loc="upper right")
    plt.grid(True)
    plt.show()


def add(a = 3, b = 4):
    print('a + b = ', a+b);
    return a+b

#pragma push_macro("slots")
#undef slots
#include <Python.h>
#pragma pop_macro("slots")

方式一 直接简单调用

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Py_Initialize();
    PyRun_SimpleString("print('hello world!')");
    Py_Finalize();
}

方式二 带有参数传递的调用

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Py_Initialize();

    //如果初始化失败,返回
    if(!Py_IsInitialized())
    {
        qDebug()<<"initial failure!";
        return a.exec();
    }

    //加载模块,模块名称为myDemo,就是myDemo.py文件
    PyObject *pModule = PyImport_ImportModule("myDemo");
    //如果加载失败,则返回
    if(!pModule)
    {
        qDebug()<<"load failure";
        return a.exec();
    }
    //加载函数getPic
    PyObject* pDict = PyModule_GetDict(pModule);
    //从字典属性中获取函数
    PyObject* pFunc = PyDict_GetItemString(pDict, "getPic");
    if(pFunc && PyCallable_Check(pFunc))
    {
        //调用函数
        //参数类型转换,传递一个字符串。将c/c++类型的字符串转换为python类型,元组中的python类型查看python文档
        PyObject* pArg = Py_BuildValue("(s)", "getPic"); 
        PyEval_CallObject(pFunc, pArg); //调用直接获得的函数,并传递参数
    }
    //如果失败则返回
    else
    {
        qDebug()<<"load function failure";
        return a.exec();
    }
    Py_Finalize();
}

方式三 带有返回结果的

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //进行初始化
    Py_Initialize();
    //如果初始化失败,返回
    if(!Py_IsInitialized())
    {
        qDebug()<<"initial failure!";
        return a.exec();
    }
    //加载模块,模块名称为myDemo,就是myDemo.py文件
    PyObject *pModule = PyImport_ImportModule("myDemo");
    //如果加载失败,则返回
    if(!pModule)
    {
        qDebug()<<"load failure";
        return a.exec();
    }
    PyObject* pDict = PyModule_GetDict(pModule);
    PyObject* pFunc = PyDict_GetItemString(pDict, "add"); //从字典属性中获取函数
    PyObject* pArg = Py_BuildValue("(i, i)", 1, 2); //参数类型转换,传递两个整型参数
    PyObject* result = PyEval_CallObject(pFunc, pArg); //调用函数,并得到python类型的返回值
    int sum;
    PyArg_Parse(result, "i", &sum); //将python类型的返回值转换为c/c++类型
    qDebug()<<"sum = "<<sum;
    Py_Finalize();
}

这两种方法不适合调用哪种需要重新开启进程做其他逻辑处理稍微复杂的事。只适合简单的参数传递并且有返回结果的, 对于如果参数是元组,列表之类那目前没有提供,需要自己查查。

方案四 直接暴力开启进程调用python

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qDebug()<< QApplication::applicationDirPath();
    QString program = "D:\\Python\\Python37-32\\python.exe";
    QStringList cmd;
    cmd<<"E:\\qt\\pyQt\\PYQTOne\\myDemo.py";
    QProcess::execute(program, cmd);
    return a.exec();
}

该方式不管你是否需要开启进程处理绘图或者其他复杂逻辑的事情,结果都可以。但是你想调用的逻辑处理 的必须自己在python里本文件调用。

关于python搜索路径参考这篇网址:
https://blog.csdn.net/fitzzhang/article/details/78988155
网址:
https://segmentfault.com/a/1190000000531613

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

道阻且长,行则降至

无聊,打赏求刺激而已

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值