gpt4 book ai didi

python - 使用python事件并与c++交互

转载 作者:行者123 更新时间:2023-12-01 14:58:22 29 4
gpt4 key购买 nike

我正在测试在C / C++程序中嵌入Python,但是我缺乏理解。

测试程序很简单:

  • 初始化解释器;
  • 从启动Timer的文件中执行python脚本(每0.1秒增加一个变量);
  • 等待5秒(C++);
  • 从字符串执行python脚本,该脚本显示由Timer
  • 事件产生的值
  • 等待5秒(C++);
  • 完成;

  • 我观察到Timer事件是在方法Py_FinalizeEx()的调用期间执行的; ;

    所以:
  • c++程序在方法Py_FinalizeEx()处停止;
  • ,C++程序无法与Py_FinalizeEx()之前或之后的事件进行交互;

  • 在事件循环期间,C++程序如何与Python程序交互?

    python代码:

    from threading import *

    count = 0;

    def foo():
    global count
    t = Timer(0.1, foo)
    t.start()
    count= count+1;
    print("foo " + str(count), flush=True)

    foo()

    C++代码

    // initialize
    Py_InitializeEx(0);

    // execute foo.py
    PyRun_SimpleStringFlags("exec(open('foo.py'.encode('utf-8')).read())",nullptr);

    // wait 5s
    qDebug() << "wait 1 begin";
    QTime t = QTime::currentTime().addSecs(5);
    while(t > QTime::currentTime());
    qDebug() << "wait 1 end";

    // display value
    PyRun_SimpleStringFlags("print(count)",nullptr);

    // wait 5s
    qDebug() << "wait 2 begin";
    t = QTime::currentTime().addSecs(5);
    while(t > QTime::currentTime());
    qDebug() << "wait 2 end";

    qDebug() << "finalize: begin";
    Py_FinalizeEx();;
    qDebug() << "finalize: end";

    结果:
    foo 1
    wait 1 begin
    wait 1 end
    wait 2 begin
    1
    wait 2 end
    finalize: begin
    foo 2
    foo 3
    foo 4
    foo 5
    foo 6
    foo 7
    foo 8
    foo 9
    foo 10

    最佳答案

    伊卡洛斯的解决方案对我有帮助:

    Surround your "wait begin" and "wait end" with Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS



    这些宏对应于以下代码:

    // Py_BEGIN_ALLOW_THREADS
    {
    PyThreadState *save
    save = PyEval_SaveThread();
    // -------------
    qDebug() << "wait 1 begin";
    QTime t = QTime::currentTime().addSecs(5);
    while(t > QTime::currentTime());
    qDebug() << "wait 1 end";
    // Py_END_ALLOW_THREADS
    PyEval_RestoreThread(save);
    }
    // --------------

    我用Qt事件开发了另一个版本:
    from threading import *

    count = 0;

    def foo():
    global count
    if count < 20:
    t = Timer(1, foo)
    t.start()
    count= count+1;
    print("foo " + str(count), flush=True)

    foo()

    #ifndef TEST_H
    #define TEST_H

    #include <QObject>
    #include <QTimer>

    #undef slots
    #include <Python.h>
    #define slots

    class PythonTest : public QObject
    {
    Q_OBJECT

    PyThreadState *save;

    QTimer _timer;
    int count = 0;

    public:
    explicit PythonTest(QObject *parent = nullptr);

    signals:

    public slots:
    void read();
    void stop();
    };

    #endif // TEST_H

    #include "pythontest.h"
    #include <QDebug>

    PythonTest::PythonTest(QObject *parent) : QObject(parent)
    {
    qDebug() << "start: begin";
    Py_InitializeEx(0);

    PyRun_SimpleStringFlags("exec(open('foo.py'.encode('utf-8')).read())",nullptr);

    _save = PyEval_SaveThread();

    _timer.setInterval(5000);
    QObject::connect(&_timer, &QTimer::timeout, this, &PythonTest::read);
    _timer.start();

    qDebug() << "start: end";
    }

    void PythonTest::read()
    {
    qDebug() << "read: begin";
    if(_count>10)
    {
    QObject::disconnect(&_timer, &QTimer::timeout, this, &PythonTest::read);
    QObject::connect(&_timer, &QTimer::timeout, this, &PythonTest::stop);
    }

    PyEval_RestoreThread(_save);
    PyRun_SimpleStringFlags("print('read ' + str(count),flush=True)");
    _save = PyEval_SaveThread();

    _count++;
    qDebug() << "read: end";
    }

    void PythonTest::stop()
    {
    qDebug() << "stop: begin";
    QObject::disconnect(&_timer, &QTimer::timeout, this, &PythonTest::stop);
    PyEval_RestoreThread(_save);

    Py_FinalizeEx();
    qDebug() << "stop: end";
    }


    输出:
    start: begin
    foo 1
    start: end
    foo 2
    foo 3
    foo 4
    foo 5
    foo 6
    read: begin
    read: end
    read6
    foo 7
    foo 8
    foo 9
    foo 10
    read: begin
    read: end
    read10
    foo 11
    foo 12
    foo 13
    foo 14
    foo 15
    read: begin
    read: end
    read15
    foo 16
    foo 17
    foo 18
    foo 19
    foo 20
    read: begin
    read: end
    read20
    foo 21
    read: begin
    read: end
    read21
    read: begin
    read: end
    read21
    read: begin
    read: end
    read21
    ...

    关于python - 使用python事件并与c++交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59307739/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com