bakercp / PacketSerial

An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
http://bakercp.github.io/PacketSerial/
MIT License
280 stars 59 forks source link

Set Packet Handler to member function #13

Closed andrewzuku closed 6 years ago

andrewzuku commented 6 years ago

Hello,

I'd like to use PacketSerial within my own class, and set the packet handler to a member function using std::bind.

For example, instead of: myPacketSerial.setPacketHandler(&onPacketReceived);

I'd want use something like: myPacketSerial.setPacketHandler(std::bind(&MyClass::onPacketReceived, this, std::placeholders::_1, std::placeholders::_2));

I imagine the PacketHandlerFunction typdef would need to be modified to use std::function instead of a static function pointer.

Is this something you'd consider supporting?

Andrew

bakercp commented 6 years ago

I considered the std::bind option, but couldn't figure out a way do it across multiple platforms (depending on the platform std::bind may not always be available).

Instead I recently added the ability to do something like this with lambda functions (see README.md)

// Instances of this class can recieve data packets when registered.
class MyClass
{
public:
    void processPacketFromSender(const PacketSerial& sender, const uint8_t* buffer, size_t size)
    {
        // Just send the buffer back to the sender.
        sender.send(buffer, size);
    }
};

MyClass myClassInstance;
PacketSerial myPacketSerial;

void setup()
{
    myPacketSerial.begin(115200);
    myPacketSerial.setPacketHandler([](const uint8_t* buffer, size_t size) {
         myClassInstance.processPacketFromSender(myPacketSerial, buffer, size);
    });
}

That said, if you can come up with a way to do it with std::bind that doesn't change the API or require further includes from other libraries, etc I'm happy to consider a pull request.

andrewzuku commented 6 years ago

The lambda function example in the README.md uses global objects.

I tried to use the "this" keyword instead, but it didn't compile. I can't figure out a way to use lambda functions while keeping the class encapsulated.

I'll play around with it bit. If I come up with anything cross-platform I'll let you know. Otherwise I'm happy for you to close this issue.

Thanks again for the excellent work!

embedded-creations commented 3 years ago

I had the same issue and got it to work by setting up the lambda function within setup(), outside of the class. Not my preferred solution, but at least it works.

  link.getPacketSerial()->setPacketHandler([](const uint8_t* buffer, size_t size) { 
    link.processPacketFromSender(*(link.getPacketSerial()), buffer, size); 
  });

(link is an instance of my class containing PacketSerial)