[Solved] How to define callback function in detail?



  • Hi all,

    I am writing an application which uses a dll. This dll can execute a callback function in the application to transfer information back into this application. Now, the callback function is prototyped like this:

    @
    typedef void (__stdcall * senn_msg_event_fn)( SENN_MSG_EVENT_ID eventid, const char * const addr, const void * const eventdata, size_t size );
    @

    How would I define the callback function in my application in detail?
    Can it be a method of a C++ object? Should it be a "normal" function outside an object?
    Do I have to create a completely separate c and header file to keep it separated?
    Which specific keywords are needed for the definition?
    Do I have to use the type (senn_msg_event_fn) in any way in the definition?
    I suppose the parameter list is used as is?

    Then, the function to declare this function to the dll is done by a call to this function:

    @
    DECLDIR SENN_MSG_ERROR senn_msg_events( const wchar_t * const addr, BOOLEAN activate, BOOLEAN persistant, BOOLEAN multicast, unsigned short udp_port, senn_msg_event_fn const callback );
    @

    Is there anything unusual I have to address when passing the function as last parameter into this call?
    Does it do any harm to call this function from within an object's method or do I have to put it into a separate c function?
    Do I really pass this function with it's name, without parenthesis, without parameter list?
    Am I referencing it by using "&"?

    Any other things I have to pay attention to within this context?

    Thanks a lot for your help!
    Stephan


  • Moderators

    bq. How would I define the callback function in my application in detail? (...) Which specific keywords are needed for the definition? (...) Do I really pass this function with it’s name, without parenthesis, without parameter list? Am I referencing it by using “&”?

    It needs to have the same signature and calling convention, for example:
    @
    void __stdcall foo( SENN_MSG_EVENT_ID eventid, const char * const addr, const void * const eventdata, size_t size ) {
    //do stuff
    }
    @
    then to pass it all you need is the name. Functions automatically decay into function pointers when context requires it so you don't need "&":
    @
    auto errorCode = senn_msg_events(addr, activate, persistant, multicast, port, foo);

    //This would work too, but it's one more letter to type. Compiler knows it anyway ;)
    auto errorCode = senn_msg_events(addr, activate, persistant, multicast, port, &foo);
    @
    You don't list any parameters when passing a function pointer just like you don't list any class members when you pass a pointer to it.

    bq. Can it be a method of a C++ object? Should it be a “normal” function outside an object?

    The typedef is for a pointer to free standing function so no, it can't be a class member. Member functions take an extra "invisible" this parameter and it is part of their signature. A notation for a member function is thus different and not exchangeable with a free standing function with the same params.

    bq. Do I have to create a completely separate c and header file to keep it separated?

    Whether or not you put your foo function in a separate header and cpp (it's a c++ project right?) is up to you. It is not required but put it where it makes structural sense for your particular app.

    bq. Do I have to use the type (senn_msg_event_fn) in any way in the definition?

    You don't need the name in neither declaration nor definition (and there's no way to do so in fact). The typedef is just a convenience to type less when you want a function pointer somewhere. For example you could write the above call to senn_msg_events as one of these:
    @
    // explicitly:
    void (__stdcall * bar)( SENN_MSG_EVENT_ID eventid, const char * const addr, const void * const eventdata, size_t size ) = foo;
    auto errorCode = senn_msg_events(addr, activate, persistant, multicast, port, bar);

    //or shorter, with the use of the typedef:
    senn_msg_event_fn bar = foo;
    auto errorCode = senn_msg_events(addr, activate, persistant, multicast, port, bar);
    @
    The important thing is that the signature is matching.

    bq. Any other things I have to pay attention to within this context?

    Worth mentioning is paying special attention to the calling convention (__stdcall in this case). If you change or omit it it will seem to compile and work but will most probably give you strange, undebuggable problems.



  • Great, thanks for the detailed answer! It confirmed some things I had in my mind already but wasn't sure about and added much benefit where I had little idea before.

    Thanks a lot!
    Stephan


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.