Тестирование интерфейса закрытой библиотеки с помощью консоли под Linux
Есть головная библиотека (dll под win, so под linux), которая тащит за собой еще множество библиотек (часть - вычислительные, часть - с GUI). Весь комплект более-менее успешно работает со своим штатным приложением GUI в обоих ОС.
Но комплект постоянно обновляется (идет этап доработки). Сборщику проекта требуется простая консольная утилитка, которая быстро протестит функционал головной библиотеки - там всего с десяток функций в экспорте. Потому что GUI слишком объемный и тяжелый, им неудобно пользоваться для первичных тестов. Кроме того, консоль нужна для оперативного подключения к библиотеке и наблюдения за ее сетевой работой.
Все библиотеки и штатный GUI написаны на Qt 5.15.2, собраны в Creator 6. Я набросал на том же самом простейшую консольную программу.
Консоль (и тестируемая через консоль библиотека) без нареканий работает под win. А вот под lin - при инициализации библиотеки в консоль поступает сообщение "QObject::startTimer: Timers can only be used with threads started with QThread". Дальше библиотека работают не полностью: часть ее функций, где есть таймирование, явно не работает.
Моя консоль не использует Qt таймеров и не формирует такое сообщение. Разработчики комплекта библиотек Qt таймеры используют, но такое сообщение тоже не формируют. Очевидно, что это сообщение Qt. Допускаю, что я не создал в консоли все необходимое "окружение" Qt, которое требуется библиотеке. Но - под win же работает!
Пробовал создать консольное приложение Qt (с QCoreApplication a(argc, argv) и return a.exec()) - тот же результат: win - библиотека работает, lin - нет.
Пробовал приложение GUI - все везде работает. Собственно, как со штатным GUI.
Наведите пожалуйста на мысль, а лучше - дайте прямое указание, что нужно дописать в консоли, чтобы у библиотеки появилось "правильная среда".
#include <qtconcurrentrun.h>
#include <iostream>
#include "sot.h"
// sim sys cmd callback
quint64 Sim_SysCmdCallback(quint64 uCode, void *p1, void *p2);
// sim app in cmd callback
quint64 Sim_AppInCmdCallback(quint64 uCode, void *p1, void *p2);
// get & print sim logs
void Sim_Logs();
// enter sim sys cmd by letter s
void Sim_EnterSysCmd(char s);
// sim console control
void Sim_Console();
// show timings info flag
bool bShowTimings=false;
using namespace QtConcurrent;
int main(int argc, char *argv[])
{
// SOT init
SO_Init(SO_INIT_APP_CON);// console mode
std::cout << "SOT init" << std::endl;
// get SOT short error message
char *pchSotErrCStrEng=(char *)SO_ErrDefStr(true,false);// pm1 true - C str fmt, pm2 false - eng lng
std::cout << pchSotErrCStrEng << std::endl;
// check SOT init errors
if (SO_Err())
{
Sim_Logs();
std::cout << "Enter 'q' to quit, any key to continue with errors:";
char c=0;
std::cin >> c;
if (c=='q')
{
SO_Term(0);
return 0;
}
}
// get this node params
SO_Cmd socmdThisNode;
SO_ThisNode(&socmdThisNode);// uP[0] - DB node Id, uP[1] - node number (UDP), uP[2] - node number (TCP), pSOCmd->pBuf - node desc name with simulator name (QString pointer)
std::cout << "This node: DBId=" << socmdThisNode.uP[0] << "; Number=" << socmdThisNode.uP[1]<< ";";
std::cout << " [sim name - node name]=[" << ((QString *)socmdThisNode.pBuf)->toStdString().c_str() << "]" << std::endl;
// get main node params
SO_Cmd socmdMainNode;
SO_MainNode(&socmdMainNode);
std::cout << "Main node: DBId=" << socmdMainNode.uP[0] << "; Number=" << socmdMainNode.uP[1]<< ";";
std::cout << " [name]=[" << ((QString *)socmdMainNode.pBuf)->toStdString().c_str() << "]" << std::endl;
// check this node is main
std::cout << "This node main status: ";
if (socmdThisNode.uP[1]==socmdMainNode.uP[1])
std::cout << "MAIN" << std::endl;
else
std::cout << "NOT-MAIN" << std::endl;
std::cout << std::endl;
// reg sys cmd callback
SO_RegSysCallback(Sim_SysCmdCallback);
std::cout << "Reg sys cmd callback" << std::endl;
// reg app in cmd callback
SO_RegAppInCallback(Sim_AppInCmdCallback);
std::cout << "Reg app in cmd callback" << std::endl;
// thread for console w wait
QFuture<void> f=run(&Sim_Console);
f.waitForFinished();
// SOT terminate
SO_Term(0);
return 0;
}
Ответы (1 шт):
Проблема решена.
- в консоли создал цикл сообщений Qt по шаблону: в начале main - QCoreApplication a(argc, argv), в конце main - return a.exec();
- задачу ввода-вывода запустил без ожидания ее окончания в main;
- по получению с клавиатуры символа прерывания задачи ввода-вывода (а заодно и завершения приложения) - вызвал QCoreApplication::quit() и вышел из задачи;
- для вызова терминальной функции библиотеки - connect этой функции с сигналом завершения приложения aboutToQuit().