callback function without brackets??

Hi Guys,
I met a little problem when I looking into the library of ESP32 library: https://github.com/espressif/arduino-esp32/blob/0cdfb0b193d9bf04adc50bf0d6020e95a28f7d21/libraries/WiFi/src/WiFiGeneric.cpp

there is a call back function onEvent():
1
2
3
4
5
6
7
8
9
10
11
12
13
wifi_event_id_t WiFiGenericClass::onEvent(WiFiEventCb cbEvent, system_event_id_t event)
{
    if(!cbEvent) {
        return 0;
    }
    WiFiEventCbList_t newEventHandler;
    newEventHandler.cb = cbEvent;
    newEventHandler.fcb = NULL;
    newEventHandler.scb = NULL;
    newEventHandler.event = event;
    cbEventList.push_back(newEventHandler);
    return newEventHandler.id;
}


the argument cbEvent is an object of function type WiFiEventCb, which is defined as this:
typedef std::function<void(system_event_id_t event, system_event_info_t info)> WiFiEventFuncCb;
my question is that, the argument cbEvent is a pointer to a callback function thus it has to contain brackets in the implementation of the calling function onEvent() to invoke the callback function, but in the implementation of onEvent(), the cbEvent doesn't have brackets.

As I know, if we want to invoke a function, we have to add brackets after the name of a function, but in library why the cbEvent doesn't have brackets but the calling function onEvent() can still invoke its callback function in arduino IDE?
I hope you can take time out of your busy schedule to help me,
Kind regards,
Last edited on
not sure what you are asking. where did you expect brackets?
if(!cbEvent) //checks if the pointer is null. nothing special needed here.

newEventHandler.cb = cbEvent; // pointer assignment. nothing special needed here.

neither use of cbEvent is anything more than pointer syntax, and in this block of code, it may as well be a pointer to an integer or anything else, its just a null check & an assignment.
when you invoke the function from its pointer, its a bit different from normal pointers, of course, but you didn't do that here.
onEvent is simply registering the callback
see _eventCallback() lines 426--439 for the calling
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    for(uint32_t i = 0; i < cbEventList.size(); i++) {
        WiFiEventCbList_t entry = cbEventList[i];
        if(entry.cb || entry.fcb || entry.scb) {
            if(entry.event == (system_event_id_t) event->event_id || entry.event == SYSTEM_EVENT_MAX) {
                if(entry.cb) {
                    entry.cb((system_event_id_t) event->event_id);
                } else if(entry.fcb) {
                    entry.fcb((system_event_id_t) event->event_id, (system_event_info_t) event->event_info);
                } else {
                    entry.scb(event);
                }
            }
        }
    }
there `entry.cb' holds your `cbEvent' function


> where did you expect brackets?
parentheses, aka round brackets, I guess
Last edited on
the argument cbEvent is a pointer to a callback function thus it has to contain brackets in the implementation of the calling function onEvent() to invoke the callback function, but in the implementation of onEvent(), the cbEvent doesn't have brackets
onEvent() is not supposed to call the function pointed to by cbEvent. onEvent() copies the callback object to a data structure so that a dispatch function later on can call it.

 
newEventHandler.cb = cbEvent;
Here, the value of cbEvent is copied to newEventHandler.cb.

 
newEventHandler.cb = cbEvent();
Here, the return value of calling cbEvent would be copied to newEventHandler.cb (per the definition of WiFiEventCb, this code would fail to compile).
Last edited on
You are misreading it. (Sorry.)

I think you are using the term “brackets” to refer to the parentheses used to invoke a function call.

Without the parentheses, the function name decomposes into a pointer to the function. This is one part of the language where you can obtain a pointer without explicitly using the & operator. That is, the following are identical:

1
2
  fn_ptr = &some_fn;
  fn_ptr =  some_fn;

In the code you reference, the cbEvent is not invoked. It is simply used to populate the list of event handlers.

At some point during execution an event occurs, the list of event handlers is traipsed, and then the event is invoked.

You will need to dig through the code a little more to find where that occurs. When you do, you will see an element of the event list having its cb member being invoked with parentheses: cb( event, info ).

Google around “C/C++ function pointers” for more introductory reading.

Hope this helps.
Topic archived. No new replies allowed.