Активирање на надворешни процеси во Qt апликации
Qt е во можност да активира надворешни процеси од вашите апликации. Може да комуницира со нив, да пишува во стандарден влез (stdin) и да чита од стандарден излез (stdout), како и да чита од стандарден излез за грешки (stderr). Во секој случај секоја извршна датотека може да биде извршена директно. Едно важно предупредување во помошната документација на Qt вели дека Qt колку и да може да манипулира со овие надворешни процеси, не може да изигрува школка за извршување низи од команди. Пример, доколку командата која се извршува во школка е:
# dmesg
може да се изврши како надворешен процес со имплементација во Qt код, но:
# dmesg|grep nesto
не можеме да ја извршиме директно како една команда. Што во тој случај поволно би било да ја спакуваме командната линија во скрипта, која би изгледала вака:
–
// skripta.sh—
#!/bin/bash
dmesg|grep nesto
// kraj skripta.sh
–
и да ја зачуваме со наставка .sh;
Потоа му задаваме извршно знаменце на скриптата (chmod +x skripta.sh) и од нашиот код можеме да ја извршиме како надворешен процес.
Класа која се грижи за сите овие работи и совршено и лесно се применува со нејзините методи и променливи е QProcess. Со оваа класа може да се прават веќе споменатите работи, како и да се испраќаат аргументи кон одредени команди (пример, ls -l, l е аргументот што треба да се испрати) како карактерен (char[n]) знак/низа.
Името на процесот кој сакаме да се изврши може да се зададе или во конструкторот на класата (дефинирајќи го објектот) или преку методот addArgument(const QString & arg) и setArguments(const QStringList & args). Можеме кога сакаме да го активираме процесот со start(QStringList * env = 0) или launch(const QByteArray & buf, QStringList * env = 0). И двата методи враќаат логичка вредност (bool) но се разликуваат според аргументите што ги примаат.
Статусот на процесот (дали е извршен, што вратил, што им праќаш и сл) може да се види преку низа методи, exitStatus(), isRunning(), readStdout(), readStderr(), writeToStdin(), секој со различен тип и број аргументи.
1.#include
2.#include
3.#include
4.
5.int main(int argc,char* argv[])
6.{
7. QApplication myApplication(argc,argv);
8.
9. // QString променлива која ќе го прими името на процесот
10. QString command;
11.
12. command=”konqueror”;
13.
14. /* Следува креирањето на инстанцата на QProcess класата која ќе ја иницијализираме во * конструкторот со QString променливата од погоре. Дефиниција на ваква променлива * може да се реализира и со динамичко доделување меморија. */
15.
16. QProcess myProcess(commandAndParameters);
17.
18. // Активирај го процесот ‘konqueror’.
19. myProcess.start();
20.
21. return 0;
22.}
Тоа што е во коментарите, објаснува се. Креираме стринг променлива и во неа ја ставаме вредноста ‘konqueror’ која впрочем е името на процесот konqueror што сакаме да го активираме, значи по активирањето на овој процес преку QProcess променливата ќе се активира апликацијата (прелистувачот) Konqueror. Сосема идентично како и кога би напишале
# konqueror
од командната линија.
Ако сакаме процесот да биде активиран кога ќе настани некакви испраќање на некој сигнал (пример clicked()), тогаш тоа го правиме исто како и во претходниот дел од упатствата (третиот), некаде во кодот (не било каде, таму каде што треба), ставаме:
connect(pushButtonName, SIGNAL(clicked()), myProcess, SLOT(myProcessStart()) );
Сега произлегуваат други прашања. Што да има во myProcessStart() ? Директно одам на тој метод (сопствен метод):
void myProcessStart()
{
myProcess->start();
}
Што забележувате? Дека во овој случај myProcess променливата мора (!) да е дефинирана како глобална променлива со динамичко доделување на слободен простор.
Читање на стандарден излез и стандарден излез за грешки
Стандарден излез е она што програмата го прикажува по нејзиното извршување. Доколку сето тоа се сведе на обид за извршување, враќа информации во стандардниот излез за грешки. Пример, ако konqueror процесот е успешен, тој може да врати некои информации кон stdout, како на пример кои библиотеки се вчитани и сл. Но излезот може да биде и NULL, т.е. само да се изврши процесот.
Ако пак врати некоја информација и процесот не се извршува тогаш мора да го читаме stderr излезот (пример апликацијата бара дополнителни пакети за да работи или паѓа веднаш на стартот).
Како да видите што се случило со процесот?
Повторно користете го механизмот на сигнали и слотови. Кога сум веќе тука надвор од контекст, мора да споменам дека има некоја тенка линија според која се разликуваат Настаните (Events) од сигналите, но во принцип се добива ист резултат. Настаните ќе ги разгледаме во некој од следните делови. Кој сигнал и кој слот треба да се поврзи? Повторно ќе е потребен еден наш метод (слот) кој ќе го прикажува тоа што QProcess променливата ќе го врати. Еве конкретен пример:
connect(myProcess, SIGNAL(readyReadStdout()), this, mySlotReader()) );
Значи како испраќач на сигналот е инстанцата myProcess на QProcess. Штом го испрати сигналот readyReadStdout() му кажува на апликацијата дека е спремна да чита од стандардниот излез и да праќа каде што треба (кон слотот, mySlotReader()). И во овој случај ќе имаме во предвид (што е многу важно) дека инстанцата myProcess мора да е дефинирана на глобално ниво.
void mySlotReader()
{
QString output(myProcess->readLineStdout());
QMessageBox::information(this, trUtf8(“Порака”), tr(output));
}
за stdErr е сосема идентично. Единствена разлика е името на сигналот што треба да го пратиме, во случајот readyReadStderr(), и името на методот преку кој ќе ја прочитаме пораката за настанатата грешка.
connect(myProcess, SIGNAL(readyReadStderr()), this, mySlotErrReader()) );
void mySlotErrReader()
{
QString output(myProcess->readLineStderr());
QMessageBox::information(this, trUtf8(“Порака”), tr(output));
}
Мала забелешка. Доколку не сте сигурни што ќе врати процесот, имплементирајте ги и поврзете ги двата методи, така едниот ќе прати за stdout, а другиот за stderr.
Тоа е тоа. Имплементацијата во кодот е во зависност од тоа што ви е потребно. Разгледајте ја документацијата на Тролтек за QProcess по што нештата ќе станат далеку појасни. Патем, има и пример за QProcess што доаѓа со Qt.
Александар Балаловски
aleksandar.balalovski@gmail.com