c++ - 如何在类中使用 termios.h 注册事件

标签 c++ termios

我正在 Linux 中制作一个 C++ 串行类。我正在尝试在收到传入数据时注册一个事件。

我正在研究 Olimex Lime2 板。 gcc 版本 4.6.3 (Debian 4.6.3-14)

这是我在尝试编译时遇到的错误。 conSerial.cpp:在函数‘void signal_handler_IO(int)’中: conSerial.cpp:15:6: 错误:“EventHandler”未在此范围内声明

我认为这意味着它无权访问该类。也许我走错了路。任何意见,将不胜感激。

谢谢,

史蒂夫

头文件

#ifndef CONSERIAL_H_
#define CONSERIAL_H_

#include "termios.h"
#include <sys/signal.h>
class conSerialEvents
{
    public:
        virtual void onReceive();
};
class conSerial
{
    public:
        conSerial(const char *port_, termios *options_, conSerialEvents *EventHandler_);
        conSerial(const char *port_, termios *options_);
        int open_port(void);
        int send(const char *s, size_t len);
        void close_port( void );
    private:

        conSerialEvents *EventHandler;
        static const int PORT_OPEN = 0;
        termios *options;
        const char *port;
        int fd;
        struct sigaction saio;  
};

#endif

类文件

#include <stdio.h>      //Standard input/output definitions
#include <string.h>     //String function definitions
#include <unistd.h>     //UNIX standard function definitions
#include <fcntl.h>      //File control definitions
#include <errno.h>      //Error number definitions
#include <termios.h>    //POSIX terminal control definitions
#include <iostream>     //Input-Output Streams
#include "conSerial.h"  //Header for this file
using namespace std;
void signal_handler_IO (int status);
void signal_handler_IO (int status)
{
    std::cout << "Signal" << std::endl;
    //This section fails because it can't see the class I think.
    if (EventHandler)
    {
        EventHandler->onReceive();
    }
    //End this section

}

conSerial::conSerial(const char *port_, termios *options_)
{
    this->EventHandler = 0L;
    const char *port;
    termios *options;
    fd = -1;

}

conSerial::conSerial(const char *port_, termios *options_, conSerialEvents *EventHandler_)
{
    this->EventHandler = EventHandler_;
    const char *port;
    termios *options;
    fd = -1;
} 

int conSerial::open_port(void){

    struct termios options;

    fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);

    if (fd == -1){
        //Could not open the port.
        std::cout << "Port Failed to Open";
    }else{
        saio.sa_handler = signal_handler_IO;
        sigemptyset(&saio.sa_mask);
        saio.sa_flags = 0;
        saio.sa_flags = SA_NODEFER;
        saio.sa_restorer = NULL;
        sigaction(SIGIO,&saio,NULL);

        fcntl(fd, F_SETOWN, getpid());      
        fcntl(fd, F_SETFL, FNDELAY); // Sets the read() function to return NOW and not wait for data to enter buffer if there isn't anything there.

        //Configure port for 8N1 transmission
        tcgetattr(fd, &options);                    //Gets the current options for the port
        cfsetispeed(&options, B38400);              //Sets the Input Baud Rate
        cfsetospeed(&options, B38400);              //Sets the Output Baud Rate
        options.c_cflag |= (CLOCAL | CREAD);        //? all these set options for 8N1 serial operations
        options.c_cflag |= PARENB;                  //? 
        options.c_cflag &= ~CSTOPB;                 //?
        options.c_cflag &= ~CSIZE;                  //?
        options.c_cflag |= CS7;                     //?

        tcsetattr(fd, TCSANOW, &options);           //Set the new options for the port "NOW"

        std::cout << "seems like everything is ok, keep going\n";
    };

    return (fd);
};

int conSerial::send(const char *s, size_t len){
    int written;
    written = 0;
    if (fd==-1){    //
        // If this is -1 it means that the port is not open.
        std::cout << "The port is not open." << std::endl;
    }else{
        // The port is open
        tcdrain(fd);
        written = write(fd, s, len);
    }
    return written;
}

void conSerial::close_port( void ){
    if (fd !=-1){
        close(fd);
    }
}

最佳答案

在您的“类文件”中,您声明了一个函数:

void signal_handler_IO (int status)

它指的是一些名为“EventHandler”的对象。

在任何地方都没有声明这样的对象,因此出现编译错误。就这么简单。

确实您声明了一个名为“conSerial”的类,它恰好有一个名为“EventHandler”的类成员。

但是,那是一个类。和类(class)成员。事实上,你有一些类恰好声明了一个同名的类成员,这绝对没有任何区别。 C++ 不是这样工作的。 signal_handler_IO 不是同一个类中的方法。它甚至不是该类中的静态类函数。要访问类成员,您需要两件事之一:在某个地方的类实例,以便访问其成员;或从同一类中的非静态方法访问它,该方法会自动访问其方法所在的任何类实例的相应成员。这就是 C++ 的工作原理。

这就是编译错误的基本解释。

的确,在名为“open_port”的不同类方法中,您获取了指向此 signal_handler_IO 函数的指针,并将其安装为 SIGIO 的信号处理程序。同样,这并没有真正改变任何东西。

看来您希望您的 conSerial 类成为单例。在这种情况下,最干净的解决方案是:

  1. 重构类,使其能够构建和销毁uses the singleton design pattern ,尽可能多。

  2. 在类的构造函数中安装信号处理程序,并在类的析构函数中卸载信号处理程序。

  3. 在安装信号处理程序之前,让构造函数在私有(private)静态类成员中保存指向 this 的指针。

  4. 将大部分 signal_handler_IO 移动到静态类方法中,并让 signal_handler_IO 除了调用静态类方法外什么都不做。

  5. 您的静态类方法是否使用在第 3 步中设置的指针访问单例类的实际实例。现在,它可以对其“EventHandler”类成员做任何它想做的事情。

关于c++ - 如何在类中使用 termios.h 注册事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41971033/

相关文章:

c++ - 在 macOS 上编译 GLEW 和 GLUT?

c++ - 是定义函数?

python - readAll() 或 readAllStandardOutput() 在执行之前返回一个空字符串

objective-c - 为什么在与 USB 转串行适配器通信时此串行通信代码会挂起?

linux - PTY/TTY - 只有从属 FD 不能做什么

c++ - 最小化全屏窗口的最佳方法

c++ - 当一个函数有一个特定大小的数组参数时,为什么它被替换为一个指针?

python - 通过 termios.TIOCSTI 注入(inject) unicode 字符

c++ - Windows 和 Linux 中 USB 串口的区别

termios - 无法导入 termios 包