c++ - 如何使用 Qt 在 Linux 中读取文件设备?

标签 c++ linux qt

我正在开发一个基于 Qt5 的小型 GUI,它将显示来自 Linux 文件设备的数据流。 为此,我选择了操纵杆输入。使用 cat/dev/input/js0 可以在终端上看到传入的流。

使用 C,您可以使用带有阻塞读取或处理设备信号的循环来读取此设备文件。但我没有用 Qt 得到这个。

使用 Qt 与设备文件交互的典型方法是什么?


基于@rodrigo 的回答,这里有一个新的实现:

joystick.h

#ifndef JOYSTICK_H
#define JOYSTICK_H

#include <QObject>
#include <QFile>
#include <QSocketNotifier>

class Joystick
      : public QObject
{
    Q_OBJECT

    QString fileName = "/dev/input/js0";
    QFile *file;
    QSocketNotifier *notifier;

public:
    explicit Joystick(QObject *parent = nullptr);
    ~Joystick();

signals:

public slots:
    void handle_readNotification(int socket);
};

#endif // JOYSTICK_H

游戏杆.cpp

#include "joystick.h"

Joystick::Joystick(QObject *parent)
   : QObject(parent)
{
    file = new QFile();
    file->setFileName(fileName);
    if( !file->exists() ){
        qWarning("file does not exist");
        return;
    }

    if( !file->open(QFile::ReadOnly) ){
        qWarning("can not open file");
        return;
    }

    notifier = new QSocketNotifier( file->handle(),
                                    QSocketNotifier::Read,
                                    this);

    connect( notifier,
             &QSocketNotifier::activated,
             this,
             &Joystick::handle_readNotification );

    if( !notifier->isEnabled() ){
        qInfo("enable notifier");
        notifier->setEnabled(true);
    }
    qInfo("Joystick init ready");
}

void
Joystick::handle_readNotification(int /*socket*/)
{
    static quint64 cnt=0;
    qInfo("cnt: %d",cnt++);

    if( !(file->isOpen()) ){
        qWarning("file closed");
        return;
    }

    char buf[16]; /* tested with different sizes */
    if( file->read(buf,sizeof(buf)) ){
        qInfo("read: %s",buf);
    }
//  QByteArray ba = file->readAll();
//  qInfo("Data: %s", ba.data());
}

然后我运行它,最后输出的是 cnt: 0。看来,readreadAll 调用现在会阻塞。如果我注释掉读取调用,计数器运行得非常快。 here a similiar post哪里错了?


最终解决方案

感谢罗德里戈!

joystick.h

#ifndef JOYSTICK_H
#define JOYSTICK_H

#include <QObject>
#include <QFile>
#include <QSocketNotifier>

class Joystick
      : public QObject
{
    Q_OBJECT

    QString fileName = "/dev/input/js0";
    QSocketNotifier *notifier;
    int fd;

public:
    explicit Joystick(QObject *parent = nullptr);
    ~Joystick();

signals:
    void buttonPressed(quint8 number, qint16 value);
    void axisMoved(quint8 number, qint16 value);


public slots:
    void handle_readNotification(int socket);
};

#endif // JOYSTICK_H

游戏杆.cpp

#include "joystick.h"

#include <fcntl.h>
#include <unistd.h>
#include <linux/joystick.h>

Joystick::Joystick(QObject *parent)
   : QObject(parent)
{
    auto file = new QFile();
    file->setFileName(fileName);
    if( !file->exists() ){
        qWarning("file does not exist");
        return;
    }

    fd = open(fileName.toUtf8().data(), O_RDONLY|O_NONBLOCK);
    if( fd==-1 ){
        qWarning("can not open file");
        return;
    }

    notifier = new QSocketNotifier( fd,
                                    QSocketNotifier::Read,
                                    this);

    connect( notifier,
             &QSocketNotifier::activated,
             this,
             &Joystick::handle_readNotification );
}

Joystick::~Joystick()
{
    if( fd>=0 ){
        close(fd);
    }
}

void
Joystick::handle_readNotification(int /*socket*/)
{
    struct js_event buf;
    while( read(fd,&buf,sizeof(buf))>0 ){
        switch (buf.type) {
        case JS_EVENT_BUTTON:
            emit buttonPressed(buf.number, buf.value);
            break;
        case JS_EVENT_AXIS:
            emit axisMoved(buf.number, buf.value);
            break;
        }
    }
}

最佳答案

这个问题通常可以通过工具包的轮询源来解决。对于 Qt,这是 QSocketNotifier .尽管它的名字(历史事故?),它可用于轮询任何文件描述符,而不仅仅是套接字。

所以你只要打开设备,用open()获取文件描述符,然后在上面创建一个QSocketNotifier,类型为QSocketNotifier::阅读。当有事件要读取时,您会收到 activate() 信号。

关于c++ - 如何使用 Qt 在 Linux 中读取文件设备?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48734421/

相关文章:

linux - Linux中的U区等效数据结构是什么?

c++ - 如何在qt中像PC开始菜单一样在状态栏中创建菜单

c++ - clang 和 gcc 中的这个警告似乎不正确

c++ - 将 C 数组导入 Eigen 变换矩阵?

Linux shell 脚本 - 在文件的第一行搜索字符串(日期)并将其复制到新文件?

c - 无法理解以下宏

c++ - 从 QGridLayout 中删除边框

qt - 通过qt在gnuplot中保存pdf输出

c++ - 线性(超定)代数方程的解

c++ - 在 C 或 C++ 中处理循环依赖的最佳方法?