связь между терминалом и gui программой |
Здравствуйте, гость ( Вход | Регистрация )
связь между терминалом и gui программой |
ht1515 |
31.1.2014, 18:00
Сообщение
#1
|
Студент Группа: Участник Сообщений: 29 Регистрация: 14.4.2012 Пользователь №: 3324 Спасибо сказали: 0 раз(а) Репутация: 0 |
Всем привет!
Есть консольная программа - терминал. Там вводятся команды, выполняются и результат сразу же печатается в программе( н-р командная строка в винде ). Я хочу ее связать с gui программой написанной на куте. Никакой сессии, общей памяти консольная программа не дает. Она подразумевает наличие оператора ПК, который тыкать будет команды. Можно ли каким-нибудь хитрым способом передавать консольной проге команды, чтобы она их выполняла и потом получать ответ? |
|
|
Sokoloff |
31.1.2014, 19:40
Сообщение
#2
|
Участник Группа: Участник Сообщений: 237 Регистрация: 1.4.2009 Из: Москва Пользователь №: 654 Спасибо сказали: 50 раз(а) Репутация: 11 |
Всем привет! Есть консольная программа - терминал. Там вводятся команды, выполняются и результат сразу же печатается в программе( н-р командная строка в винде ). Я хочу ее связать с gui программой написанной на куте. Никакой сессии, общей памяти консольная программа не дает. Она подразумевает наличие оператора ПК, который тыкать будет команды. Можно ли каким-нибудь хитрым способом передавать консольной проге команды, чтобы она их выполняла и потом получать ответ? Никакого хитрого способа не надо, используй QProcess. Вот реальный пример из моей программы https://github.com/flacon/flacon/blob/maste...litter.cpp#L127 Смотри метод Splitter::doRun() У меня, правда, немного другая ситуация, я запускаю программу, передаю в нее данные, закрываю STDIN, а потом читаю из STDOUT-а, но очень близко к твоему случаю, тебе не надо дергать closeWriteChannel. |
|
|
ht1515 |
31.1.2014, 20:46
Сообщение
#3
|
Студент Группа: Участник Сообщений: 29 Регистрация: 14.4.2012 Пользователь №: 3324 Спасибо сказали: 0 раз(а) Репутация: 0 |
ммм... спасибо. Посмотрю. Я прокомментирую ,вы поправьте если что. Цитата QStringList args; args << "split"; args << "-w"; args << "-O" << "always"; args << "-n" << "%04d"; args << "-t" << mFilePrefix +"%n"; args << "-d" << mWorkDir; args << disk()->audioFileName(); //qDebug() << args; формирование входных параметров консольной программы. Необходимы при запуске программы. Цитата QString shntool = settings->value(Settings::Prog_Shntool).toString(); Видимо путь до программы. Цитата mProcess = new QProcess(); mProcess->setReadChannel(QProcess::StandardError); создание объекта процесса и установка ??? канала на чтение ошибок? Цитата mProcess->start(shntool, args); mProcess->waitForStarted(); Запуск процесса( консольной программы) и ожидание ее готовности к работе. Цитата sendCueData(); Отправка каких-то данных. Пока не углубляюсь куда и каких данных. В этой функции mProcess->write(" INDEX 01 00:00:00\n"); --- Видимо что-то пишется в консоль программы(cin, stdin) Цитата mProcess->closeWriteChannel(); закрыли процесс записи в консольку. Это имитация нажатия кнопки enter? Цитата parseOut(); Производим чтение результата выполнения команды. По сути чтение с консоли и парсинг. Цитата mProcess->waitForFinished(-1); блокировка потока пока процесс консольной программы не будет завершет. Цитата QProcess *proc = mProcess; mProcess = 0; delete proc; garbage collector Цитата if (OutFormat::currentFormat()->createCue()) { CueCreator cue(disk()); cue.setHasPregapFile(mPreGapExists); if (!cue.write()) error(disk()->track(0), cue.errorString()); } Какая-то работа с файлом. |
|
|
Sokoloff |
1.2.2014, 0:11
Сообщение
#4
|
Участник Группа: Участник Сообщений: 237 Регистрация: 1.4.2009 Из: Москва Пользователь №: 654 Спасибо сказали: 50 раз(а) Репутация: 11 |
Все что я не комментирую правильно.
Цитата mProcess = new QProcess(); mProcess->setReadChannel(QProcess::StandardError); создание объекта процесса и установка ??? канала на чтение ошибок? У консольной программы есть 3 потока: STDIN - входные данные, обычно он связан с клавиатурой, но может быть и чем то другим. Например "dir | sort" sort получает на вход выхлоп ls. STDOUT - выходной, сюда печатаются обычные выходные данные. STDERR - выходной, сюда выводятся сообщения об ошибках. Деление между последними условное, так принято. И, если STDOUT все используют по назначению, то в STDERR выводят не только ошибки, а все что не должно путаться с STDOUT-ом. В моем случае на STDERR выводятся проценты выполнения работы. Именно они меня и интересуют, поэтому я говорю QProcess-у что его readXXX функции будут читать STDERR. Цитата mProcess->closeWriteChannel(); закрыли процесс записи в консольку. Это имитация нажатия кнопки enter? Нет это имитация окончания входного файла. Например если запустить программу "sort < file.txt", то sort будет читать данные из файла file.txt до тех пор пока он не кончится. А после уже отсортирует и выведет их, так вот closeWriteChannel это имитация окончания файла. Или в случае "dir | sort" окончание работы первой программы. Вот это тебе делать и не надо, не закрывай канал. А enter передается обычным переводом строки("\n"). Да, еще. Консольная программа может получать команды разными методами. Стандартный подход через STDIN, и тогда мой подход сработает. Но программа может сама обрабатывать нажатия клавиатуры, и тогда придется извращаться. |
|
|
ht1515 |
1.2.2014, 15:48
Сообщение
#5
|
Студент Группа: Участник Сообщений: 29 Регистрация: 14.4.2012 Пользователь №: 3324 Спасибо сказали: 0 раз(а) Репутация: 0 |
Вчера вечером почитал
http://doc.crossplatform.ru/qt/4.7.x/qproc...waitForFinished Нашел такой пример, gzip заменил на gdb. Цитата QProcess gdb; gdb.start("gdb", QStringList() << "-c"); if (!gdb.waitForStarted()) return false; QByteArray result = gdb.readAll(); // Это чтобы вычерпать "шапку", которую печатает gdb при запуске gdb.write("print"); gdb.closeWriteChannel(); if (!gdb.waitForFinished()) return false; QByteArray result = gdb.readAll(); // должен прочитать результата команды в gdb Чуть-чуть изменил код. Но все равно result выдает все. И шапку и результат выполнения команды и даже (gdb)> Я вроде понял о чем вы, но не могу собрать пока велосипед, чтобы он поехал как надо. Что не так сделал я? вроде логично рассуждаю) небольшая правка Цитата gdb.start("gdb"); а не Цитата gdb.start("gdb", QStringList() << "-c"); просто в редакторе форума код правил |
|
|
Sokoloff |
1.2.2014, 20:54
Сообщение
#6
|
Участник Группа: Участник Сообщений: 237 Регистрация: 1.4.2009 Из: Москва Пользователь №: 654 Спасибо сказали: 50 раз(а) Репутация: 11 |
Но все равно result выдает все. И шапку и результат выполнения команды А никто не обещал, что waitForStarted ждет пока программа будет готова принимать данные от пользователя, да еще и проскипает вводное сообщение. Для этого нужен искин. waitForStarted ждет пока ОС прочитает экзешник, выделит всякие PID-ы и.т.п, т.е. чисто на низком уровне. А дальше сам читаешь и парсишь. и даже (gdb)> А чем "(gdb)>" отличается от другого текста? Обычная строка, только без перевода каретки. Я накидал простой пример класса работы с gdb
Не совершай стандартной ошибки новичков, никто не гарантирует, что в момент вызова procOutDataReady, процесс успел выплюнуть весь текст, вполне возможна ситуация, процесс напечатал пол слова, и в этот момент Qt решило эти данные обработать. Т.е. readAllStandardOutput вернет на все данные, а все которые готовы на этот момент. Поэтому надо накапливать в буфере. Я обрабатываю и STOUT и STDERR, причем немного по другому чем в моей программе. Возможно через события тебе будет удобнее. Обрати внимание, QString хранит в юникоде, процесс выдает в локальной кодировке, обязательно преобразовывать через fromLocal8Bit и toLocal8Bit При вводе команды, надо добавлять "\n". Желательно завершать программу корректно, я посылаю "quit" в gdb и даю ему 5 сек. на завершение. Я не скипаю приглашение, если надо, то можно добавить условие, и при первом вызове procOutDataReady не выводить текст. |
|
|
Текстовая версия | Сейчас: 22.11.2024, 9:34 |