I am doing something like this:
#include <signal.h>
class myClass {
public:
void myFunction ()
{
signal(SIGIO,myHandler);
}
void myHandler (int signum)
{
/**
* Handling code
*/
}
}
I am working on Ubuntu, using gcc.
But it won't compile. It is complaining with:
error: the argument with type
void (MyClass::)(int)
doesn't agree withvoid (*) (int)
Any clues? Or maybe it is just that I cannot use a signal inside classes? Are signals only allowed in C?
The error message is an approximate translation because my compiler is not in English.
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 :-)!