Не удается скомпилировать макрос F() с помощью R "string"
Я пытаюсь скомпилировать следующий код:
logger.log_info(F(R"(некоторый текст здесь, который может занять
несколько строк
и вот это сделано.)"));
Но компилятор существует со следующей ошибкой:
ошибка: необработанная необработанная строка
Я могу использовать либо R
, либо F
, но не оба вместе. Как я должен иметь возможность использовать их вместе?
1 ответ
Лучший ответ:
Если вы поставите:
#define DO_NOTHING(s) (s)
DO_NOTHING(R"xyz(Hello
World)xyz")
вы можете видеть, что g ++ прерывает предварительную обработку необработанного строкового литерала при вызове макроса с последним пакетом платы esp8266 на момент написания (версия 2.7.4). Это поставляется с g ++ 4.8.2 для xtensa.
~/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-4-b40a506/bin/xtensa-lx106-elf-g++ -E donothing.h
Возможно, вам потребуется настроить командную строку для вашей системы. ничего не делай.h - это просто макрос и вызов, описанные выше.
Результат:
# 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")
Этого не происходит с g ++ 9.3.0 на целевой платформе amd64 Linux.
В качестве обходного пути вы можете восстановить (более или менее) то, что макрос F() делает со следующим:
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);
}
Могу я спросить вас, зачем вам писать что-то за скобками литерала? (а именно *xyz* в вашем примере)? Если это все равно не будет показано, @Mohammed Noureldin
Есть ли у вас какие-либо предложения по преобразованию выходных данных FPSTR (pgm_str)
в std::string? потому что это тип аргумента, который я использую. Это ошибка, которую я получаю сейчас: нет известного преобразования для аргумента 1 из 'const __FlashStringHelper *' в 'const string& {он же const std::basic_string<char>&}
, @Mohammed Noureldin
std::string работает путем выделения из динамической памяти, за исключением, возможно, небольших строк, поэтому для того, чтобы получить одну из них, вам нужно будет скопировать в нее. Другими словами, в какой-то момент у вас будет вторая копия в оперативной памяти. Что вы в конечном счете делаете со строкой? КСТАТИ: класс arduino String обычно принимает const __FlashStringHelper * , но это не то, чего вы в конечном итоге хотите, и было бы немного глупо загружать его в один, а затем в другой., @timemage
Вы правы, спасибо за это замечание. Это означает, что использование const char *
вместо String или std::string
должно быть в порядке вещей в этом случае, так как никакого копирования не произойдет, и я буду в порядке, если использую эту строку для ведения журнала. Верно?, @Mohammed Noureldin
Я не уверен, что понимаю. Откуда берется logger.log_info? Это опубликованная библиотека, на которую вы можете мне указать? Я спрашиваю, потому что, если это было сделано с учетом Arduino, вполне вероятно, что в нем уже есть некоторая поддержка для чтения строк из "PROGMEM"., @timemage
Нет, на самом деле это не так, это написано когда-то мной, данные журнала - это просто некоторые строки, которые будут созданы во время выполнения. Например: logger.log_info("Текущее время" + time);
. И аргумент, который он принимает, - std::string
, я могу просто изменить его, конечно, на const char *
. Однако теперь, после изменения типа аргумента, компилятор по-прежнему жалуется на тип: `ошибка: нет соответствующей функции для вызова 'Logger::log_info(const __FlashStringHelper *) const".
Не могли бы вы продолжать пытаться помочь мне, пожалуйста, решить эту проблему? Я все равно приму ответ, потому что главный вопрос был решен!, @Mohammed Noureldin
Хех, к сожалению, это ужасная среда для того, чтобы пытаться поддерживать беседу. Вероятно, существует какая-то политика, запрещающая предлагать это, но вы можете найти меня на irc.freenode.net в #arduino я могу попытаться отредактировать ответ, чтобы включить процедуру загрузки std::string из __FlashStringHelper, если хотите. Или, я полагаю, это могло бы просто перейти в комментарий, поскольку это не является частью фактического ответа на вопрос., @timemage
Давайте [продолжим это обсуждение в chat](https://chat.stackexchange.com/rooms/116022/discussion-between-mohammed-noureldin-and-timemage)., @Mohammed Noureldin
- Какова цель F() и FPSTR() в ESP8266WebServer -> FSBrowser?
- Утечка памяти, вызванная конкатенацией строк
- ESP8266 12-E не может подключиться ни к одной точке доступа с преобразованными переменными из строк в массивы символов
- Как отправить данные ads1115 через spi на master arduino
- Как отправлять информацию о данных без работы Wi-Fi на LCD?
- Как запрограммировать ардуино на чистом C/C++?
- Создание форматированной строки (включая числа с плавающей запятой) в Arduino-совместимом C++
- Передача функции-члена класса в качестве аргумента
Вы пробовали завершить строку вручную, добавив
\0
в конец? Возможно, это помогает, так как сообщение об ошибке жалуется на то, что строка не завершается, @chrisl@chrisl поскольку я использую
R
, как\0
должно оцениваться как завершение строки?, @Mohammed Noureldin@chrisl, я пробовал, но я не могу скомпилировать, потому что весь оставшийся файл теперь оценивается как часть строки. Так что это не сработало., @Mohammed Noureldin
Некоторое время назад были некоторые ошибки с необработанными строковыми литералами и препроцессором в GCC. Какую версию вы используете?, @Mat
@Mat, библиотеки Arduino 2.7.4; GCC: 7.3.0, @Mohammed Noureldin