Search code examples
c++callbackgcc4.7

Giving a method as a callback function (gcc 4.7.1)


I'm trying to set a seemingly-simple callback method pointer into a variable and get the following error:

CSerialSniffer.cpp|11|error: cannot convert ‘CSerialSniffer::AsyncRecieverReceived’ from type ‘Nexus::TReceiveCallback (CSerialSniffer::)(Nexus::CData*, Nexus::IMetaData*)’}’| to type ‘Nexus::typeAsyncReceiverCallback {aka Nexus::TReceiveCallback ()(Nexus::CData, Nexus::IMetaData*)}’|

Here is the set statement:

typeAsyncReceiverCallback l_pPointer = AsyncRecieverReceived;

And I have the following defined:

typedef TReceiveCallback (*typeAsyncReceiverCallback)(CData *a_pData, IMetaData *a_pMetaData);

class CSerialSniffer
{
...
public:
    Nexus::TReceiveCallback AsyncRecieverReceived(Nexus::CData *a_pData, Nexus::IMetaData *a_pMetaData);
...
}

I've been at this for hours now, any ideas?

In response to answers: I have the same callback mechanism here:

typedef void (*EnqueueCallback)( PData *pd );

class SomeClass
{
...
public:
   void enqueue( PData *pd );
...
};


class CSerialSniffer
{
...
public:
    void set_enqueue_callback(EnqueueCallback a_pEnqueueCallback );
...
}


SomeClass::SomeFunction(){
 this->serialSniffer->set_enqueue_callback(this->enqueue);
}

And it compiles well. What's the difference between the two?


Solution

  • Your CSerialSniffer::AsyncRecieverReceived is a member function. It cannot be used without an object, so either you make it a free function (outside the class), or a static function:

    class CSerialSniffer
    {
    ...
    public:
        static Nexus::TReceiveCallback AsyncRecieverReceived(
             Nexus::CData *a_pData, 
             Nexus::IMetaData *a_pMetaData);
    ...
    };
    
    typeAsyncReceiverCallback l_pPointer = &CSerialSniffer::AsyncRecieverReceived;
    

    A better alternative with C++11 is to use a std::function<> instead:

    typedef std::function<TReceiveCallback(CData*,IMetaData*)> 
            typeAsyncReceiverCallback;
    

    Now you can create a free function by binding an object as the first argument of the member function:

    CSerialSniffer snivver;
    
    auto callback = std::bind( 
         std::mem_fun( &CSerialSniffer::AsyncRecieverReceived ),
         &snivver );
    

    These goodies are in ther <functional> header.