views:

570

answers:

3

Ok folks let me see if i can explain this clearly...

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 wont compile... It driving me nuts. It is complaining with:

error: the argument with type 'void (MyClass::)(int) don't agree with 'void (*) (int)

Any clues?? Or maybe is just that I cannot use signal inside classes? May it be only a C stuff?

Just for the record, the error message is an approximate translation cuz my compiler is not in English.

+2  A: 

Read this following section (33.2):

C++ FAQ

Baget
+5  A: 

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.

Jørn Jensen
+1  A: 

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 :-)!

Luc Touraille
Your second example isn't standard C++.
dalle
Is that because I forgot the static keyword? If so, it's corrected!
Luc Touraille