KEIL. Настройка компоновки для .c и .cpp файлов.

При создании проекта с использованием C++, часто подключаются разные файлы .c или .cpp.

KEIL между разными файлами может не видеть внешние функции и сообщаться об этом ошибкой: Error: L6218E: Undefined symbol  xxxxxxxxxxxxxxxxxxxx (referred from main.o).

Это связано с тем что линковщик ругается на компоновку. Не видит из других модулей.

 

Ключевое слово extern объявляет переменную или функцию и указывает, что она имеет внешние компоновки (ее имя будет видимым не только в пределах файла, в котором она определена, но и в других файлах). Когда выполняется изменение переменной, ключевое слово extern обозначает, что переменная имеет статическую длительность (она выделяется в начале программы и высвобождается при завершении). Переменная или функция может быть определена в другом исходном файле или позднее в том же самом файле. Объявления переменных и функций в области видимости файла являются внешними по умолчанию.

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


Чтобы вызвать функцию C из C++, используйте следующую нотацию преобразования типов:
 extern "C" void my_func (void); 
Это сообщает компоновщику, что для функции my_func требуется компоновка для модуля на языке С++ с соглашением языка С.

Есть два пути решения:

1. В модуле обьявить стиль C для всех внешних ссылок.

В файле MyFile.h нужно добавить:

#include «cmsis_os2.h»
#include «stm32f10x.h»

#ifdef __cplusplus
extern «C» {
#endif

extern uint16_t BUF;
extern void TFT_START(void);

#define TFT_RST_LOW GPIOB->BRR = (1<<7) //CS = L
#define TFT_RST_HIGH GPIOB->BSRR = (1<<7) //CS = H

#ifdef __cplusplus
}
#endif

 

Это позволит компилировать в зависимости от настроек компилятора.

2. Это самостоятельно указывать соглашение для каждой внешней ссылки.

К пример есть два модуля  main.cpp и display.c

В модулей main.cpp есть реализация функции Delay, чтобы модуль display.c ее увидел нужно обьявить ее прототип как внешняя в модуле main.h.

extern void Delay (uint32_t Count);

Компоновщик не увидит ее из-за разницы соглашений, для этого добавляем соглашение.

extern «C» void Delay (uint32_t Count);

После этого компоновщик будет видеть ее и функция станет доступна другим модулям которые используют ее.

В случае, если модули используются одинаковые, тогда достаточно одного обьявления прототипа в модуле display.c

extern void Delay (uint32_t Count);

Удачной компиляции без ошибок!

Оставить ответ