Nitay
Nitay

Reputation: 4710

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?

Upvotes: 0

Views: 245

Answers (2)

Jan Spurny
Jan Spurny

Reputation: 5537

Your callback declaration

typeAsyncReceiverCallback

is regular function, but

AsyncReceiverReceived

is a method (i.e. it NEEDS "this" pointer and there's no way it can get it this way in c++).

Either change AsyncReceiverReceived to static or use the observer pattern.

Upvotes: 2

xtofl
xtofl

Reputation: 41519

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.

Upvotes: 3

Related Questions