LiamBindle / MQTT-C

A portable MQTT C client for embedded systems and PCs alike.
https://liambindle.ca/MQTT-C
MIT License
766 stars 269 forks source link

Adding contex to callbacks #143

Closed alex-bohmeraudio closed 2 years ago

alex-bohmeraudio commented 2 years ago

This is a question. In the examples we have:

void publish_callback(void** unused, struct mqtt_response_publish *published);

I'm using MQTT-C and callbacks in a threaded environment and would like to add a context parameter to the callbacks. For example paho mqtt async library has (ref)

int MQTTAsync_setCallbacks(MQTTAsync handle, \
    void * context, \
    MQTTAsync_connectionLost * cl, \
    MQTTAsync_messageArrived * ma, \
    MQTTAsync_deliveryComplete * dc
)

The second parameter allows to add application-specific context to the callbacks.

According to MQTT-C docs it seems that the last parameter in mqtt_init(), i.e. the callback, allows for passing context information - publish_response_callback_state. However, it's unclear for me how to use this in practice. How can the specific context pointer be registered together with the callback?

More details how I use MQTT-C:

I have an init function that is called when application starts, it initializes the client once. mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), check_callbacks);

I use check_callbacks, which is checking all registered callbacks. Various plugins in the application registers callbacks during init using subscribing_subscribe:

static void (*pf[CALLBACKS_MAX])(void** unused, struct mqtt_response_publish *published) = {NULL};

static void check_callbacks(void** unused, struct mqtt_response_publish *published){
    for(int i=0; i<CALLBACKS_MAX; ++i){
        //printf("cb[%d]: %p\n", i, fp[i]);
        if( pf[i] ){
            pf[i](unused, published);
        }
    }
}
...
void subscribing_subscribe(const char topic[], void (*cb)){
    ...
    /* subscribe */
    printf("Listening for %s messages\n", topic);
    mqtt_subscribe(&client, topic, 0);

    if(callbacks < CALLBACKS_MAX){
        pf[callbacks] = cb;
        callbacks++;
    }else{
        printf("WARNING. Reached max number of callbacks: %d", CALLBACKS_MAX);
    }
    ...
}

So, I would like to add void * context to the parameters in subscribing_subsccribe() and somehow make sure that the context is passed as the void ** unused parameter in check_callbacks().

Having looked little more into the code, specifically mqtt_init(), __mqtt_recv, and struct mqtt_client I think that I understand that my application context should be is stored in the struct. That suggests that each plugin in my application should create it's own mqtt_client.

/Alex.

alex-bohmeraudio commented 2 years ago

Fixed