[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 -
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