Пишу класс работающий с трафиком RS485 порта. При открытии порта я указываю функцию, вызываемую при наличии во входном буфере порта каких-то данных:
struct sigaction saio; /* definition of signal action */
fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the device to be non-blocking (read will return immediatly) */
if (fd <0) { perror(device);}
sigemptyset(&saio.sa_mask); /* install the signal handler before making the device asynchronous */
saio.sa_handler = signal_handler_IO;
Если функция - обработчик описана как обучная функция:
void signal_handler_IO (int status){
if (read(fd,&buf,1)){
std::cout << "I'm recieve byte\t" << std::hex << buf[0] << std::dec << std::endl;
}
}
То проблем нет. Но если я эту функцию делаю членом класса, то возникают ошибки компиляции.
error: cannot convert ‘Rs485::signal_handler_IO’ from type ‘void (Rs485::)(int)’ to type ‘__sighandler_t {aka void (*)(int)}’
Я в C++ не очень силен и не понимаю что от меня хочет компилятор. Скажите пожалуйста, как мне сделать членом класса функцию-обработчик ?
Во-первых, sa_handler имеет тип void (*)(int), поэтому сделать можно будет не много.
Это либо стандартная функция, как в C,
void handler(int);
saio.sa_handler = &handler;
, либо анонимная функция без свободных переменных (начинающаяся с [])
saio.sa_handler = [](int sig){ /* ... */ };
, либо статический член класса
struct Saio {
static void handler(int sig) { /* ... */ }
};
saio.sa_handler = &Saio::handler;
. При этом все три могут принимать лишь один аргумент типа int, а о контексте (инкапсулированном в объекте-обработчике состоянии) никто и не подумал.
Ну то есть все данные, нужные обработчику, либо предполагаются глобальными
std::ostream &os = std::cout;
struct Saio {
static void handler(int sig) { os << "Signal #" << sig << std::endl; }
};
, либо во всяком случае статическими на уровне класса (Александреску пишет, что это и есть Monostate pattern):
class Saio {
static int handlerData;
static std::string moreHandlerData() { return "Hello" };
public:
static void setData(int x) { handlerData = x; }
static void handler(int sig) {
os << moreHandlerData()
<< ", this is handler#" << handlerData << " speaking, I've got signal"
<< sig << std::endl;
}
};
int Saio::handlerData = 42;
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости