【问题标题】:Arduino: pass function to class, returning StringArduino:将函数传递给类,返回字符串
【发布时间】:2017-05-17 09:44:44
【问题描述】:

我正在尝试让我的 Arduino 类返回带有各种日志信息的字符串消息。经过大量试验和错误,我设法将日志记录函数的引用传递给类,但只能得到一个 char* 而不是一个字符串,我希望能够发送字符串,从而更容易发回所有各种数据。

我已经完成了第一部分。 草图:

#include <Test.h>
#include <string.h>

void setup() {
  Serial.begin(115200);
  Test t;
  t.setLogging(writeLog);
  writeLog("Test message!" + String(" .... "));
  t.doSomething("This is useful.");
  t.doSomething("This as well.\n");
  t.doSomething("This is even more useful.\n");
  bool b = true;

}

void loop() {
}

void writeLog (char* message) {
  Serial.print("char function: ");
  Serial.print(message);
}

void writeLog (String message) {
  Serial.print("String function: ");
  Serial.println(message);
}

头文件:

#ifndef TEST_h
#define TEST_h

class Test
{
  public:
    Test();       // The constructor.
    void setLogging(void (*)(char*)); // Takes function setting where to log.
    void doSomething(char*);
};

#endif

班级:

#include <Test.h>

typedef void (*LogFunction)(char*);
LogFunction writeLog;

Test::Test () { 
}

void Test::doSomething (char* s) {

  // Do something useful and log the result.
  writeLog(s);
}

void Test::setLogging (void (*f)(char*) ) {
  writeLog = f;
  return;
}

现在我希望我的班级能够发送这样的信息,作为字符串,而不是 char*(我还没有找到一种简单的方法将“任何”转换为 char*,然后将两者连接起来或更多字符串):

writeLog ("HydroMonitorECSensor::setCalibration  Receiving calibration - haveCalibration = " + String(haveCalibration));
writeLog ("HydroMonitorECSensor::setCalibration  calibratedSlope = " + String(calibratedSlope));
writeLog ("HydroMonitorECSensor::setPins  capPos set to " + String(capPos));

其中haveCalibrationbool(字符串变为“真”或“假”),calibratedSlopedoublecapPosint。这样我可以轻松干净地将完整的行发送到记录器。在主脚本中效果很好 - 而不是在课堂上。

我尝试简单地将char* 更改为String 并将#include &lt;string.h&gt; 添加到库文件中,但它不起作用。

然后在 Test.cpp 中我得到 void Test::setLogging (void (*f)(String) ) { 和在 Test.h 中 void setLogging(void (*)(String)); 现在我得到错误消息:

In file included from /home/wouter/Arduino/libraries/Test/Test.cpp:1:0:
/home/wouter/Arduino/libraries/Test/Test.h:10:29: error: expected ',' or '...' before '(' token
     void setLogging(void (*)(String)); // Takes function setting where to log.
                             ^
/home/wouter/Arduino/libraries/Test/Test.cpp:16:40: error: variable or field 'setLogging' declared void
 void Test::setLogging (void (*f)(String) ) {
                                        ^
/home/wouter/Arduino/libraries/Test/Test.cpp:16:31: error: 'f' was not declared in this scope
 void Test::setLogging (void (*f)(String) ) {
                               ^
/home/wouter/Arduino/libraries/Test/Test.cpp:16:34: error: 'String' was not declared in this scope
 void Test::setLogging (void (*f)(String) ) {
                                  ^
exit status 1
Error compiling for board NodeMCU 1.0 (ESP-12E Module).

建议?

附加信息,也许很重要:我正在使用 Arduino IDE 并为 ESP8266 进行编译。

【问题讨论】:

    标签: c++ string arduino


    【解决方案1】:

    您正在使用 Arduino 提供的 String 类,但未在 test.h 头文件中包含 Arduino.h 头文件。这会导致它找不到String 类并且编译失败。

    以下作品:

    main.cpp:

    #include <Arduino.h>
    #include <test.hpp>
    
    void writeLog (char* message);
    void writeLog (String message);
    
    void setup() {
      Serial.begin(115200);
      Test t;
      t.setLogging(writeLog);
      writeLog("Test message!" + String(" .... "));
      t.doSomething("This is useful.");
      t.doSomething("This as well.\n");
      t.doSomething("This is even more useful.\n");
      bool b = true;
    
    }
    
    void loop() {
    }
    
    void writeLog (char* message) {
      Serial.print("char function: ");
      Serial.print(message);
    }
    
    void writeLog (String message) {
      Serial.print("String function: ");
      Serial.println(message);
    }
    

    test.hpp:

    #ifndef TEST_h
    #define TEST_h
    
    #include <Arduino.h> //for "String" class
    
    //Typdef for the log function. Takes a String, returns nothing
    typedef void (*LogFunction)(String);
    
    class Test
    {
      public:
        Test();       // The constructor.
      //  void setLogging(void (*)(char*)); // Takes function setting where to log.
        void setLogging(LogFunction); //use the typedef here
        void doSomething(char*);
    };
    
    #endif
    

    test.cpp:

    #include <test.hpp>
    
    
    LogFunction writeLog;
    
    Test::Test () {
    }
    
    void Test::doSomething (char* s) {
    
      // Do something useful and log the result.
      writeLog(s);
    }
    
    //void Test::setLogging (void (*f)(char*) ) {
    void Test::setLogging (LogFunction f) { //also use typedef here
      writeLog = f;
      return;
    }
    

    【讨论】:

    • 是的,这行得通!实际上,我之前确实尝试过添加 Arduino.h,但肯定是做错了什么,因为它没有用。在我的主要草图中,我也没有包含它,但它仍然可以编译,从不需要这个 Arduino.h,不知道它是如何工作的......感谢您的快速回答。
    • 想一想,我可能没有尝试包含Arduino.h,不太确定,因为我尝试了很多,最后却完全沮丧地尝试了这个和那个,但没有任何效果,但是我确实尝试过包含string.h。后者毕竟是我在普通草图中需要能够使用String 类型。
    【解决方案2】:

    除了可能出现的其他情况外,编译器会告诉您它无法解析标识符String。 这可能有几个原因:首先,你写的是String,而不是string(注意你写的大写字母)。其次,如果您写的是string 而不是std::string,除非您声明了using namespace std(由于多种原因,这不是首选的变体)或using std::string,否则它无法解决。第三,类std::string在标题&lt;string&gt;中声明,这与&lt;string.h&gt;不同。

    所以我会写#include &lt;string&gt;,然后使用std::string

    【讨论】:

    • 这使用了 Arduino String 类,而不是 std::string
    • 这是标准 C/C++ 和 Arduino 之间的区别(发布的代码在 Arduino IDE 中编译良好)。 String 是 Arduino 版本,std::string 是 C 版本,两者不兼容。我实际上尝试了 std::string 并没有让它工作。
    • @Maximilian Gerhardt:好的;我认为 OP 针对的是 c++-string 类。 +1 指出了这一点。顺便说一句:为什么 std::string 不起作用?
    • 不太清楚为什么它不起作用。部分问题可能是我最终混合了两种名称几乎相同的类型,几乎相同的包括(string vs string.h)等。这当然是自找麻烦。将各种类型转换为std::string 看起来也不像String 那样简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    • 2013-12-11
    • 1970-01-01
    • 2011-05-12
    相关资源
    最近更新 更多