Как установить (* sa_handler) (int) указатель на функцию, которая является членом класса?(неверное использование нестатической функции-члена) - PullRequest
0 голосов
/ 31 января 2019

Я не эксперт по C ++ и пытаюсь создать класс, который обрабатывает нажатие на терминале ctrl + C.

Мои методы работали до того, как я начал перемещать их в класс SignalHandler.

Похоже, я не могу установить sigaction.sa_action в:

 sigIntHandler.sa_handler = SomeClass->someMethod(int s);

, как я мог бы в C.

sigIntHandler.sa_handler = someMethod(int s);

Компилятор говорит:

signals.cpp: In constructor ‘SignalHandler::SignalHandler()’:
signals.cpp:5:39: error: invalid use of non-static member function
     registerSignalHandler(ctrlCHandler);
                                       ^

Что не так с моим кодом?

Полагаю, мне нужно преобразовать функцию-член класса в что-то вроде этого: (*sa_handler)(int).

cpp file:

#include "signals.h"

SignalHandler::SignalHandler() {
    isSigtermReceived = false;
    registerSignalHandler(ctrlCHandler);
}

SignalHandler::~SignalHandler() {
}

// private

void SignalHandler::registerSignalHandler(void (*handler)(int)){
    struct sigaction sigIntHandler;
    sigIntHandler.sa_handler = handler;
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGINT, &sigIntHandler, NULL);
}

void SignalHandler::ctrlCHandler (int s) { 
    using namespace std;

    cout << endl << "Caught signal " << s << ". Exiting." << endl;
    isSigtermReceived = true;
}

h file:

#ifndef SIGNALS_H
#define SIGNALS_H

#include <signal.h> // ctrl-c
#include <iostream>

class SignalHandler {
    public:
        SignalHandler();
        virtual ~SignalHandler();
        bool isSigtermReceived;
        void registerSignalHandler(void (*hnd)(int));
    private:
        void ctrlCHandler(int s);
};

#endif /* SIGNALS_H */

И это структура, в которой я пытаюсь присвоить sa_handler поле:

struct sigaction {
    void     (*sa_handler)(int);
    void     (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t   sa_mask;
    int        sa_flags;
    void     (*sa_restorer)(void);
};

(http://man7.org/linux/man-pages/man2/sigaction.2.html)

1 Ответ

0 голосов
/ 31 января 2019

Вы не можете преобразовать функцию-член в указатель на функцию.

Несмотря на фактическую семантику, вы можете просто думать, что функция-член имеет скрытую ссылку this, которую нельзя передать какуказатель свободной функции.

Самое простое решение - использовать метод моста, который позаботится об этом, например:

class SignalHandlerDispatcher {
private:
  static SignalHandler* _handler;

public:
  static void setHandler(SignalHandler* handler) { _handler = handler; }
  static void sa_handler(int v) { _handler->SomeMethod(v); }
};

, так что теперь вы можете использовать SignalHandlerDispatcher::sa_handler в качестве обратного вызова,так как это static.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...