Is it possible to use signal inside a C++ class?
#include <signal.h>
class myClass {
private:
static myClass* me;
public:
myClass(){ me=this; }
void myFunction (){
signal(SIGIO,myClass::myHandler);
}
void my_method(){ }
static void myHandler (int signum){
me->my_method();
}
}
The second parameter of signal should be a pointer to a function accepting an int and returning void. What you're passing to signal is a pointer to a member function accepting an int and returning void (its type being void (myClass::*)(int)
). I can see three possibilities to overcome this issue:
1 - Your method myHandler
can be static: this is great, make it static
class myClass
{
public:
void myFunction ()
{
signal(SIGIO, myClass::myHandler);
}
static void myHandler (int signum)
{
// handling code
}
};
2 - Your method shouldn't be static: if you're planning to use signal with only one instance, you can create a private static object, and write a static method that simply call the method on this object. Something along the lines of
class myClass
{
public:
void myFunction ()
{
signal(SIGIO, myClass::static_myHandler);
}
void myHandler (int signum)
{
// handling code
}
static void static_myHandler(int signum)
{
instance.myHandler(signum);
}
private:
static myClass instance;
};
3 - However, if you're planning on using the signal with multiple instances, things will get more complicated. Perhaps a solution would be to store each instance you want to manipulate in a static vector, and invoking the method on each of these :
class myClass
{
public:
void myFunction () // registers a handler
{
instances.push_back(this);
}
void myHandler (int signum)
{
// handling code
}
static void callHandlers (int signum) // calls the handlers
{
std::for_each(instances.begin(),
instances.end(),
std::bind2nd(std::mem_fun(&myClass::myHandler), signum));
}
private:
static std::vector<myClass *> instances;
};
and somewhere, do a single call to
signal(SIGIO, myClass::callHandlers);
But I think that if you end up using the last solution, you should probably think about changing your handling design :-)!
To pass a pointer to a method, it must be a static method and you must specify the class name.
Try this:
class myClass {
void myFunction ()
{
signal(SIGIO, myClass::myHandler);
}
static void myHandler (int signum)
{
// blabla
}
};
And you should also read the link supplied by Baget, the paragraph 33.2 in the C++ FAQ.
Actually, C++ signal handlers are not permitted to use any facilities not present in both C and C++ (except that in C++11 they may use atomics), and are required to use C linkage. Quoting C++11 draft n3242 section 18.10 "Other runtime support" [support.runtime] (paragraph 8),
The common subset of the C and C++ languages consists of all declarations, definitions, and expressions that may appear in a well formed C++ program and also in a conforming C program. A POF (“plain old function”) is a function that uses only features from this common subset, and that does not directly or indirectly use any function that is not a POF, except that it may use functions defined in Clause 29 that are not member functions. All signal handlers shall have C linkage. A POF that could be used as a signal handler in a conforming C program does not produce undefined behavior when used as a signal handler in a C++ program. The behavior of any other function used as a signal handler in a C++ program is implementation-defined.
(Clause 29 being the one on atomics.)