Оценка прогресса встроенного скрипта Python в C ++ - PullRequest
0 голосов
/ 28 февраля 2019

Введение

Допустим, у меня есть приложение на C ++ со встроенным скриптом Python.Скрипт выполняет некоторые сложные вычисления, которые требуют значительного времени для завершения.Я могу извлечь результат сценария, когда он закончен.Однако было бы удобно узнать, каково действительное время расчета - это 10% или, может быть, половина работы уже выполнена?Вот пример кода (с использованием boot python):

app.cpp

#include <iostream>
#include <boost/python.hpp>

using namespace boost::python;

int main()
    try
    {
    Py_Initialize();
    object module = import("__main__");
    object name_space = module.attr("__dict__");
    exec_file("Script.py", name_space, name_space);

    object MyFunc = name_space["MyFunc"];
    object result = MyFunc();

    double sum = extract<double>(sum);}

Py_Finalize();

Script.py

def MyFunc():
    cont = 0
    while (cont < 10000):
        #...some calculations here, increasing "result" value on each step...
        cont +=1
    return result

Проблема

Если бы весь код был на C ++, я мог бы использовать встроенные инструменты фреймворка, такие как emit, чтобы получить доступ к слоту индикатора выполнения GUI и обновить его значение.Но что в случае, описанном выше?В консольном приложении я мог печатать cont каждый раз, прямо с python.Однако это не решение для любого C ++ с GUI.Есть ли способ определить, на уровне кода C ++, на каком этапе цикла выполняется Script.py?Или, может быть, есть какое-то другое решение, чтобы обслуживать индикатор?

Ответы [ 2 ]

0 голосов
/ 10 марта 2019

Подводя итог выводам из раздела комментариев: Проблема может быть решена путем вызова функции, вызываемой из python..Cpp будет выглядеть так:

#include <iostream>
#include <boost/python.hpp>

using namespace boost::python;

int main(){
    Py_Initialize();
    object module = import("__main__");
    object name_space = module.attr("__dict__");
    exec_file("Script.py", name_space, name_space);

    object MyFunc = name_space["MyFunc"];
    object result = MyFunc();

    double sum = extract<double>(sum);}

    Py_Finalize();}

callback(int cont){
    int cont_final = 10000;
    double progr = cont / cont_final * 100;
    cout << cont << "\n";}

Имейте в виду, что обратный вызов должен быть статическим членом или свободной функцией (в этом случае я показал второй вариант).Если вам нужно передать также состояние (например, из-за графического интерфейса), посмотрите ЗДЕСЬ .

Часть Python будет:

def MyFunc(callback):
    cont = 0
    while (cont < 10000):
        #...some calculations here, increasing "result" value on each step...
        cont +=1
        callback(cont) #Here we call progress update
    return result

И это все - вРезультаты выполнения индикатора от 0 до 100 будут напечатаны на консоли.

0 голосов
/ 28 февраля 2019

Вы можете отправить сигнал из программы python обратно в программу C ++, что-то вроде:

if cont % 100 == 0:
    os.kill(cpp_progs_pid, signal.SIGUSR1)

, а затем использовать обработчик сигнала для этого сигнала в C ++, чтобы использовать emit.

РЕДАКТИРОВАТЬ: В вашем коде C ++ вам нужно передать pid программы, что-то вроде этого:

#include <sys/types.h>
...
int pid = getpid(); // python's cpp_progs_pid
exec_file("Script.py", name_space, name_space, pid);

И что-то вроде этого для обработки сигнала:

#include <signal.h>
...
void my_handler(int signum)
{
    if (signum == SIGUSR1)
    {
        // code to use emit
    }
}
...
signal(SIGUSR1, my_handler);  // set your signal handler

обработчик сигнала my_handler будет вызываться асинхронно во время работы вашей программы на C ++, поэтому вы должны быть осторожны с любыми побочными эффектами.Он должен быть установлен один раз перед вызовом скрипта Python.

...