Комментарии изменяют поведение компиляции (переопределение слабой ссылки sysTickHook)

У меня есть очень простая процедура, которая загорается встроенным светодиодом (вывод 13), когда системный таймер срабатывает при прерывании.

Я переопределяю слабую ссылку на int sysTickHook(пустоту), найденную в hooks.c. Я обнаружил, что в целом для этого мне нужно использовать внешнюю связь "C"

Часть, которая вызывает недоумение, заключается в том, что это прерывание срабатывает нормально без "C", если над ним есть комментарии, как показано ниже. Это минимальный воспроизводимый пример, который я могу найти. Кто-нибудь может это объяснить?

Я использую старую простую Arduino IDE 1.8.16.

void setup() {
  pinMode(13,OUTPUT);  
  digitalWrite(13,LOW);
}

void loop() {}

// {          -- если вы удалите эту строку, системный вызов не будет вызван
// extern "C" -- если вы удалите эту строку, sysTickHook не будет вызываться
int sysTickHook()
{        
  digitalWrite(13,HIGH);
  return 0;
}

, 👍2

Обсуждение

Вероятно, это прототипы функций, которые вставляет IDE, нарушают его., @Majenko

Как на них повлияет наличие комментария?, @Adam V. Steele

Я бы изучил это подробнее, но если бы я собирался приложить к этому усилия, я бы хотел знать, какой пакет поддержки платы вы использовали и какая плата была выбрана., @timemage

@timemage Я не устанавливал ничего стороннего и не изменял ни одну из установленных библиотек. Я добавил через менеджера платы "Платы Arduino SAM 1.6.12". Для компиляции и загрузки я просто использую раскрывающийся список "Arduino Due (порт программирования)". Подробное описание гласит " Использование платы "arduino_due_x_dbg" с платформы " Какую еще информацию я могу предоставить?, @Adam V. Steele


1 ответ


Лучший ответ:

2

Проблема заключается в препроцессоре в среде IDE. Это недостаточно умно, чтобы разработать внешнюю букву "C" при добавлении прототипов функций.

С вашими комментариями вы получите:

#include <Arduino.h>
#line 1 "/home/matt/t/t.ino"
#line 1 "/home/matt/t/t.ino"
void setup();
#line 6 "/home/matt/t/t.ino"
void loop();
#line 10 "/home/matt/t/t.ino"
 extern "C" int sysTickHook(); // << The extern gets added here from the comment
#line 1 "/home/matt/t/t.ino"
void setup() {
  pinMode(13,OUTPUT);  
  digitalWrite(13,LOW);
}

void loop() {}

// {          -- если вы удалите эту строку, системный вызов не будет вызван
// extern "C" -- если вы удалите эту строку, sysTickHook не будет называться
int sysTickHook()
{        
  digitalWrite(13,HIGH);
  return 0;
}

Он находит внешнее в комментарии и думает, что это реальный код. Если вы удалите маркеры комментариев, это приведет к нарушению кода, так как у вас есть случайный { там. Если вы полностью удалите комментарии, вы получите функцию в связи C++, которая внутренне изменяет имя функции и затем не переопределяет слабую функцию. То же самое произойдет, если вы удалите только первый комментарий.

По сути, наличие этих комментариев нарушает работу препроцессора таким образом, что он работает. Правильный способ сделать это таков:

void setup() {
  pinMode(13,OUTPUT);  
  digitalWrite(13,LOW);
}

void loop() {}

extern "C" {
  int sysTickHook()
  {        
    digitalWrite(13,HIGH);
    return 0;
  }
}
,

Обработка комментариев как кода-это довольно большая ошибка! Может ли препроцессор Arduino IDE действительно быть сломан таким образом?, @Adam V. Steele

@AdamV.Стил Уверен, что это возможно. Он менее сломан, чем раньше, - он даже помещал прототипы в совершенно неправильное место и пресекал любые попытки использовать структуры в качестве параметров., @Majenko

@AdamV.Стил, лол, добро пожаловать в Arduino., @timemage