0

I need to pass variables to a lamda expression inside a method. To do this I'm using the & operator in the capture list.

(I'm using the AppleMIDI library.)

// MIDIService.h

#ifndef MIDIService_h
#define MIDIService_h

#include <AppleMIDI.h>

// ...

class MIDIService {
   public:
    MIDIService();

    void setup(const uint8_t midiOnValue,
               // ...
               void (*onConnected)());

   // ...

};

#endif
// MIDIService.cpp

#include "MIDIService.h"


MIDIService::MIDIService() {}

void MIDIService::setup(const uint8_t midiOnValue,
                        // ...
                        void (*onConnected)()) {

    // ...

    // AppleMIDI.setHandleConnected is from the AppleMIDI library.
    AppleMIDI.setHandleConnected([&](const APPLEMIDI_NAMESPACE::ssrc_t& ssrc, const char* name) { // ERROR!
        onConnected();
    });
    
    // ...

    // MIDI.setHandleControlChange is from the AppleMIDI library.
    MIDI.setHandleControlChange([&](byte channel, byte number, byte value) { // ERROR!
        if (value == midiOnValue) {
            // ...
        } else {
            // ...
        }
    });
}

But VSCode spits out:

no suitable conversion function from "lambda [](const appleMidi::ssrc_t &ssrc, const char *name)->void" to "void (*)(const appleMidi::ssrc_t &, const char *)" exists

and

no suitable conversion function from "lambda [](byte channel, byte number, byte value)->void" to "midi::ControlChangeCallback" exists

I researched about this error but couldn't find a solution that worked for me. Being a C++ newbie I also had trouble understanding half of them.

JakesMD
  • 1,646
  • 2
  • 15
  • 35
  • 7
    A lambda with captures can't be converted to a function pointer. – tkausl Sep 13 '22 at 19:10
  • @tkausl Not easily, anyway. The amount of abstraction needed to make it work will just muddy the code horrendously. Might be better to just take up the extra bulk of `std::function`. Once they're spun up, they're pretty fast. – sweenish Sep 13 '22 at 19:19
  • The error message and your title do not match. – user17732522 Sep 13 '22 at 19:25
  • @sweenish he uses [Arduino API](http://arduinomidilib.sourceforge.net/a00001.html#ae32bf8fb641ac7bc74714329ca449e2c) which accept only function pointers (without custom context), so there is no way to use capturing lambda and he can't alter this API (so no `std::function`). – Marek R Sep 13 '22 at 19:26
  • I'm guessing `onConnected` is a non-static member of your `MIDIService` class? From the link you provide it looks as if (under certain circumstances at least) the service name is passed as the second parameter `name` to your callback. Is that not sufficient to allow you to effectively look up this `MIDIService` instance by some means and then call `onConnected` against it? – G.M. Sep 13 '22 at 19:28
  • @MarekR I seem to see this issue here quite often for Arduino. Do you know why Arduino libraries tend to accept raw pointers without giving any way to provide a user context pointer? Not doing so seems like an obvious design flaw to me. – user17732522 Sep 13 '22 at 19:29
  • @user17732522 Sorry Arduino is not my thing. – Marek R Sep 13 '22 at 19:35
  • @MarekR Are you basically saying that it is not possible to fix this error in my case? I guess the only way to fix this is to scrap the MIDIService idea and just run the code in the Arduino setup function. Just means that the code may end up a little messy in main.cpp (or main.ino) and won't match the rest of my architecture/project setup. – JakesMD Sep 13 '22 at 20:26
  • 1
    @JakesMD have you looked at the duplicate? There are answers that would absolutely work for your situation. – Drew Dormann Sep 13 '22 at 20:31
  • The simplest workaround is global variable (or `MIDIService` as singleton), but I hate such solutions. – Marek R Sep 14 '22 at 08:37
  • I got it to work btw. using [this solution](https://stackoverflow.com/a/63349217/11979688) and by listing the individual variables in the capture list instead of using `&`. If we reopen this question I can add this solution as an answer. – JakesMD Sep 17 '22 at 07:07

0 Answers0