Задать вопрос
Ответы пользователя по тегу C++
  • Почему сигнал ReadyRead() вызывается только один раз?

    vxblog
    @vxblog
    Инженер-программист
    Что ж, с вашего позволения, устрою небольшое code review.

    Установка параметров порта.
    Да, метод setPortName не возвращает ничего. Но, вызовы QSerialPort::setBaudRate, QSerialPort::setDataBits, QSerialPort::setParity, QSerialPort::setStopBits и QSerialPort::setFlowControl могут вернуть false. Пытаться открыть после этого порт явно не стоит. Лучше вызвать QSerialPort:error, чтобы обработать ошибку.

    Сигналы и слоты.
    1. Cоединить сигнал QSerialPort::readyRead со слотом ComPort::HandleReadyRead можно сразу после создания экземпляра QSerialPort. До установки параметров порта и его открытия.
    2. Однозначно, необходимо подключить сигнал QSerialPort::errorOccurred и реализовать обработку ошибок. Ну хотя бы их вывод в консоль во время отладки.
    3. Пожалуйста, не используйте макросы SIGNAL и SLOT. Переходите на функторы.


    QObject::connect (com_port_, &QSerialPort::readyRead, this, &ComPort::handleReadyRead);
    QObject::connect (com_port_, &QSerialPort::errorOccurred, this, &ComPort::handleError);


    Открытие порта.
    Метод QSerialPort::open следует вызывать только после успешной установки параметров порта (см. выше). И даже после этого он может вернуть false. В этом случае ничего не остаётся, как вызвать QSerialPort:error, чтобы отреагировать на ошибку. Кстати, это рекомендации из официальной документации.

    Чтение данных.
    Во-первых, метод чтения данных QSerialPort::read может вернуть -1 в случае ошибки. А метод QSerialPort::readAll в случае ошибки вернёт пустой QByteArray. Что нужно делать в этом случае? Правильно! Вызвать QSerialPort:error, чтобы отреагировать на ошибку.

    Во-вторых, я бы не стал полагаться на каждое срабатывание сигнала QSerialPort::readyRead, а использовал бы цикл с методом QIODevice::bytesAvailable, в котором считываются и обрабатываются все данные, о приходе которых стало известно по упомянутому выше сигналу.
    void ComPort::HandleReadyRead()
    {
      while (serial_->bytesAvailable () > 0) {
    
        // Чтение данных
        QByteArray data = serial_->readAll ();
        if (data.isEmpty ()) {
          handleError ();
          return;
        }
    
        read_buffer_.append (data);
    
        // Здесь ещё пристуствует логика обработки сообщения, я ищу символ конца
        // сообщения, и если его нахожу, то эмитирую сигнал, для вызова слота парсинга сообщения.
      }
    }


    В-третьих, на момент закрытия порта он может располагать данными, которые вы не успели прочитать. Для обработки этой ситуации, метод чтения данных следует вызвать перед закрытием порта. Возможно, это не ваш случай. Но, на моей практике он бывал много раз.

    Обработка ошибок.
    Простите, но у вас она отсутствует как класс. Реализуйте, например, предлагаемый мною ComPort::handleError.
    void ComPort::handleError (QSerialPort::SerialPortError error)
    {
      qDebug () << __LINE__ << __FUNCTION__ << error;
    }


    Заключение.
    На мой взгляд, только после указанных выше доработок можно приступить к рассмотрению вопроса по существу. И вообще хоть как-то локализовать проблему.
    Ответ написан
    Комментировать
  • Как устранить ошибку библиотеки C++ при обновлении игры?

    vxblog
    @vxblog
    Инженер-программист
    Приложение с обновлением завершило свою работу аварийно. Вы запускаете его в Windows 7, а ему необходим функционал, доступный в Windows 10. Поэтому, это приложение аварийно завершает свою работу. Ровно об этом и сообщает Microsoft Visual C++ Redistributable - что приложение завершило свою работу, но вовсе не так, как ожидалось.

    Единственный выход - это запустить приложение в подходящем для него окружении, с теми библиотеками из состава Windows 10, которые этим приложением используются. Больше информации можно найти в журналах системы или приложения, если они пишутся.

    В переустановке Microsoft Visual C++ Redistributable никакого особого смысла нет, ведь дело совершенно не в нём. Можно спокойно оставить самую свежую версию пакета.
    Ответ написан
    Комментировать