I am trying to compile the following code:
logger.log_info(F(R"(some text here that may take
multiple lines
and here it is done.)"));
But the compiler exists with the following error:
error: unterminated raw string
I am able to use either R
or F
, but not both together. How should I be able to use them together?
1 Answer 1
If you put:
#define DO_NOTHING(s) (s)
DO_NOTHING(R"xyz(Hello
World)xyz")
you can see g++ choke on preprocessing the raw string literal in the macro invocation with the latest esp8266 board package as of writing (version 2.7.4). This comes with g++ 4.8.2 for xtensa.
~/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-4-b40a506/bin/xtensa-lx106-elf-g++ -E donothing.h
You may need to adjust the command-line for your system. donothing.h is just the macro and invocation described above.
Result:
# 1 "donothing.h"
# 1 "<command-line>"
# 1 "donothing.h"
donothing.h:3:13: warning: missing terminating " character [enabled by default]
DO_NOTHING(R"xyz(Hello
^
(R"xyz(Hello World)
donothing.h:4:10: warning: missing terminating " character [enabled by default]
World)xyz")
^
xyz")
This does not happen with g++ 9.3.0 on an amd64 Linux target.
As a workaround you can reconstruct (more or less) what the F() macro does with the following:
void setup() {
Serial.begin(9600);
}
void loop() {
static const char pgm_str[] PROGMEM = (R"xyz(Hello
World)xyz");
Serial.println(FPSTR(pgm_str));
delay(4000);
}
-
May I ask you why would you write something outside of the parenthesis of the literal? (namely xyz in your example)? If this is not gonna be shown anywayMohammed Noureldin– Mohammed Noureldin2020年11月10日 00:50:38 +00:00Commented Nov 10, 2020 at 0:50
-
Do you have any suggestion to convert the output of the
FPSTR(pgm_str)
to std::string? because the is the type of the argument I am using. This is the error I get now:no known conversion for argument 1 from 'const __FlashStringHelper*' to 'const string& {aka const std::basic_string<char>&}
Mohammed Noureldin– Mohammed Noureldin2020年11月10日 00:55:22 +00:00Commented Nov 10, 2020 at 0:55 -
1std::string works by allocating from dynamic memory, except maybe for small strings, so in order to wind up with one you'd need to copy into it. In other words, at some point you'll have a second copy in RAM. What are you ultimately doing with the string? BTW: the arduino String class usually accepts const __FlashStringHelper *, but this inn't what your ultimately want and it would be a little nuts to load it into one and then the other.timemage– timemage2020年11月10日 01:04:24 +00:00Commented Nov 10, 2020 at 1:04
-
You are right, thanks for that point. That means, using
const char *
instead ofString or std::string
should be fine in this case, as no copying will happen and I will be fine to use this string for logging. Right?Mohammed Noureldin– Mohammed Noureldin2020年11月10日 01:08:22 +00:00Commented Nov 10, 2020 at 1:08 -
I'm not sure I understand. Where does logger.log_info come from? Is this a published library you can point me to? I ask, because if it was made with the Arduino in mind, it is likely that there is some support in it already for reading strings out of "PROGMEM".timemage– timemage2020年11月10日 01:13:03 +00:00Commented Nov 10, 2020 at 1:13
0円
to the end? Maybe that helps, as the error message complains about the string not being terminatedR
, how should0円
be evaluated as string termination?