Q:

Arduino: pass function to class, returning String

I'm trying to get my Arduino class to return String messages with all kind of information for logging. With lots of trial and error I manage to pass a reference to the logging function to the class, but can only get a char* but not a String, and I want to be able to send Strings making it so much easier to send back all kinds of data.
I have the first part working already.
The sketch:
#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);
}

The header file:
#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

The class:
#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;
}

Now what I want my class to be able to do is send information like this, as String, rather than char* (I also haven't found an easy way of converting "anything" to char* and then concatenating the two or more strings):
writeLog ("HydroMonitorECSensor::setCalibration  Receiving calibration - haveCalibration = " + String(haveCalibration));
writeLog ("HydroMonitorECSensor::setCalibration  calibratedSlope = " + String(calibratedSlope));
writeLog ("HydroMonitorECSensor::setPins  capPos set to " + String(capPos));

Where haveCalibration is a bool (which as String becomes either "true" or "false"), calibratedSlope is a double and capPos is an int. This way I can easily and cleanly send complete lines to the logger. Works great within the main script - not from the class.
I tried simply changing the char* to String and adding #include <string.h> to the library files but it doesn't work.
In Test.cpp I then get void Test::setLogging (void (*f)(String) ) { and in Test.h void setLogging(void (*)(String)); and now I get error messages:
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).

Suggestions?
Additional info, maybe important: I'm using the Arduino IDE and compile for ESP8266.

A:

You are using the Arduino-provided String class, but didn't include the Arduino.h header in your test.h header file. That causes it to not find the String class and compilation fails.
The following works:
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;
}

