从数组 class 属性填充并执行回调

Populate and execute callbacks from array class attribute

我最近开始学习 C++/Arduino,并且正在努力抽象我的一些 Arduino 代码,以使其更易于管理。 我正在尝试构建一个 class,其中包含 2 个数组作为其属性,一个用于存储表示命令的字符串,第二个用于存储指向这些函数的指针。

下面的代码 有效 (编译),但是当上传到设备时 listenexecute 函数似乎都不起作用。我找了很多地方,但找不到我哪里出错了。

/* main.ino */

// SETUP
#include "SoftwareSerial.h"
SoftwareSerial bt(btRx, btTx);

#include "CMD.h"
const int cmdMax = 6;
ArriCMD cmd;

// COMMANDS
void cmdStatus()
{
  Serial.println("OK");
}

// START
void setup()
{
  Serial.begin(9600);
  bt.begin(9600);
  
  cmd.add("AH+STAT", cmdStatus);
}

void loop()
{
  cmd.listen(bt);
}
/* ArriCMD.h */

#ifndef ArriCMD_h
#define ArriCMD_h

#include "Arduino.h"
#include "SoftwareSerial.h"

class ArriCMD
{
  public:
    ArriCMD();
    void add(String cmd, void (*cb)());
    void listen(SoftwareSerial serial);
    void execute(String cmd);

  private:
    int _max = 16;
    int _amt = 0;
    String _cmds[16];
    void (*_cbs[16])();
};
/* ArriCMD.cpp */

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "ArriCMD.h"

ArriCMD::ArriCMD()
{
  //
}

void ArriCMD::add(String cmd, void (*cb)())
{
  if (_amt < _max) {
    _cmds[_amt] = cmd;
    _cbs[_amt] = *cb;
  }
}

void ArriCMD::listen(SoftwareSerial serial)
{
  if (serial.available()) {
    String cmd = serial.readString();
    Serial.print(cmd);
    execute(cmd);
  }
}

void ArriCMD::execute(String cmd)
{
  for (int i = 0; i < _amt; i++) {
    if (cmd == _cmds[i]) {
      _cbs[i]();
    }
  }
}

虽然我从事编程已有十多年,但 C++ 和微控制器对我来说是全新的,我们将不胜感激任何和所有帮助。

一旦我对自己的代码质量感到更加满意,我确实打算开源这些库以及它们所针对的后续平台。

您似乎忘记增加命令计数器 _amt

void ArriCMD::add(String cmd, void (*cb)())
{
  if (_amt < _max) {
    _cmds[_amt] = cmd;
    _cbs[_amt] = *cb;
    _amt++;  // <-- here, don't you need it?
  }
}

除此之外,在您的代码中使用原始数组和原始函数指针是否有某些特殊原因?我不使用 Arduino,所以我不确定,但也许这个解决方案更简洁:

class ArriCMD
{
  public:
    ArriCMD();
    void add(String cmd, std::function<void()> cb);
    void listen(SoftwareSerial serial);
    void execute(String cmd);

  private:
    std::map<String, std::function<void()> > _cmdMap;
};