Тестирование интерфейса закрытой библиотеки с помощью консоли под 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 шт):

Автор решения: Константин

Проблема решена.

  1. в консоли создал цикл сообщений Qt по шаблону: в начале main - QCoreApplication a(argc, argv), в конце main - return a.exec();
  2. задачу ввода-вывода запустил без ожидания ее окончания в main;
  3. по получению с клавиатуры символа прерывания задачи ввода-вывода (а заодно и завершения приложения) - вызвал QCoreApplication::quit() и вышел из задачи;
  4. для вызова терминальной функции библиотеки - connect этой функции с сигналом завершения приложения aboutToQuit().
→ Ссылка