Skip to content

New feature - Pass context to result function #3

@fra87

Description

@fra87

Hi
First of all thank you for the good work.

I just have a feature request (I'm already coding it, but since it changes the interfaces of your library I'm asking here before trying to contribute with a PR).

Usually when you have callbacks in libraries you try to give the user possibility to share something custom, so that it can use it to, for instance, refer to the parent object. With callbacks I saw it being done with void pointers. So what I'm doing is:

  • In the header:
    • Redefine the ResultHandler to accept a void pointer
    • Make all functions accepting ResultHandlers to accept also the pointer
    • Of course store the pointer alongside resultHandler in the class
  • In the source file:
    • Initialize resultCtx in the constructor to nullptr
    • Have the init function store the passed value in resultCtx
    • Every time the init function is called, pass also the new context
    • Pass the value back in the callback

Code in the header file:

typedef void (*ResultHandler)(NonBlockingModbusMaster &mb, void *ctx);
[...]
bool readCoils(uint8_t slaveId, uint16_t address, uint16_t qty, ResultHandler handlerFn = NULL, void *ctx = nullptr);
// And all the other functions, including init
[...]
// context to be passed to the result handler
void *resultCtx;

Code in the source file:

resultCtx = nullptr;
[...]
resultCtx = ctx;
[...]
if (!init(_u8MBSlave, resultHandler, resultCtx)) {
[...]
if (!init(slaveId, handlerFn, ctx)) {
[...]
if (resultHandler) {
  resultHandler(*this, resultCtx); // can start another cmd
}

Why bother to do all this? Because then in the callback I can process the custom object however I need. For instance, if I have an object managing the MODBUS communication, I can pass it to the function and then get it back in the callback:

void static_cb(NonBlockingModbusMaster &mb, void *ctx)
{
  MyParser *obj = (MyParser *) ctx;
  [...] // Collect the Response Buffer
  obj->parse(stuff_from_response_buffer);
}

void MyParser::request()
{
  this->_nbModbusMaster.readHoldingRegisters(slaveId, address, qty, static_cb, (void*) this);
}

void MyParser::parse(my_type something_from_response_buffer)
{
  // Here I'm again in the parser
}

The alternative is to save MyParser instance in a static variable, but this is far less flexible

If you want to have a look at the complete code I wrote to modify the library I can share it on github and create a PR to you :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions