Вы можете захотеть вызывать C-функции из своего проекта на C++. Альтернативно Вы также можете захотеть вызывать функции C++ из проекта C. В этой статье (перевод [1]) описывает несколько моментов, которые следует учесть, когда смешиваете код C и C++. Обратите внимание, что это руководство не претендует на полноту, однако показывает некоторые общие проблемы и способы их решения.
Следует учесть следующее:
1. Необходимо использовать линковку проекта в стиле языка C (C-linkage). Для этого в заголовочные файлы поместите extern "C" { // здесь декларации Ваших функций }. Имейте в виду, что это требуется сделать как для заголовочных файлов C++, так и для заголовочных файлов C:
• Чтобы C-функция могла вызвать функцию C++. • Чтобы метод C++ смог вызвать функцию C.
2. У языка C++ более строгая проверка типов. Для примера рассмотрим следующую функцию C:
voidLCD_DisplayString(constuint8_t*text);
Эту функцию на языке C можно вызвать так:
LCD_DisplayString("RTOS START");
На языке C++ это не сработает, понадобится сделать приведение "RTOS START" к типу uint8_t* (из типа char*), чтобы подобный вызов мог скомпилироваться. Есть решение лучше, чем приведение типа (cast), см. пункт 3.
3. Оберните C-интерфейсы в классы C++. Например, вышеупомянутая функция LCD_DisplayString может быть обернута в класс LCD::DisplayString(). С помощью перезагрузки языка C++ (overloading), преобразование типа между char* и uint8_t* можно скрыть внутри методов класса LCD:
void LCD::DisplayString(constchar*text);
void LCD::DisplayString(constuint8_t*text);
Другими словами, таким способом в своем коде C++ Вы можете везде избежать кастинга типов.
4. В некоторых областях C++ ведет себя по-другому. Например, переменная:
constint myglobal;
... не является глобальной в C++, поскольку глобальные константы C++ линкуются статически. Также, например, volatile-доступ не обязательно выполняется на C++:
В то же время на C осуществляется volatile-доступ (спецификации языков C и C++ отличаются, когда к объекту осуществляется доступ в void-контексте). Чтобы избежать проблем, убедитесь, что компилируете чистый код C как C (например, код RTOS или BSP с расширением имен файлов ".c"). Имейте в виду, что компилятор C++ выдаст предупреждение на приведенный выше код: "Warning[Pe174]: expression has no effect" (выражение не имеет никакого действия).
5. Если Вы хотите использовать C-код в своих приложениях C++, рассмотрите возможность сборки C-кода в отдельном проекте (как библиотека). Вы можете поместить проект библиотеки C в том же рабочем пространстве (workspace), что и проект C++, чтобы можно было быстро переключаться между проектами.
Пример такого смешивания проектов см. в архиве [3].
Если сравнивать встраивание C-кода в группу C++ проекта с библиотекой, библиотека дает следующие преимущества:
• Четкое разделение между разными опциями компилятора. • Ускорение сборки приложения (не требуется заново собирать код, зафиксированный в библиотеке).
6. Если Ваша библиотека C это RTOS, то есть дополнительная трудность с использованием кучи RTOS, кода запуска (RTOS startup) и т. д. [2]. Часто поставщик RTOS может помочь с предоставлением примеров на C++, документацию и/или код. И снова, если код RTOS написан на C, компилируйте его как C, чтобы избежать проблем.
Technical Note 93670 C-RUN - Non-checked code (bounds checking) site:iar.com. Technical Note 92391 Handle C++ "new" memory exhaustion site:iar.com. Technical Note 24687 Code size limitation persist site:iar.com. Technical Note 46979 Any binary notation in C-source? site:iar.com. Technical Note 90935 Position independent code and data (ROPI and RWPI) site:iar.com. Technical Note 45456 C source for CRC32 site:iar.com. Technical Note 24725 Disable MISRA C for #include files site:iar.com. Technical Note 11872 Size comparison of "Hello World" using C, Embedded C++ or full C++ site:iar.com. Technical Note 92924 Linking blocks in a specified order site:iar.com.