Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Работа с препроцессором  (Прочитано 14461 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
Boriska
Помогающий

ua
Offline Offline

« : 09-09-2021 09:08 » 

Привет форумчане.
Есть контроллер STM32. И у него есть библиотеки старая SPL и новая HAL.
Предствалены они в виде хидеров и сырцов.
Захотел я работать с двумя, а там в хидерах масса повторных определений.
Редактировать как-то хидеры от производителя не хочется.
вставил я межу ними свой файл с отменой повторных определений.
#include "oldlibrary.h"
#include "myundefinefile.h"
#include "newlibrary.h"

ну и там повставлял
#undef повторноеопределение1
#undef повторноеопределение2
#undef повторноеопределение3

поборол, но там еще оказались повторные typedef

typedef имятипа1....
попробовал #undef имятипа1
не фурычит и ничего толгового не придумал.
Подскажите кто знает пожалуйста.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 09-09-2021 14:39 » new

Boriska, привет. Включай заголовки разных библиотек исключительно в разные единицы трансляции. Тогда пересечений не будет

Добавлено через 43 секунды:
язык то какой ? Си или C++ ? Стандарт какой?
« Последнее редактирование: 09-09-2021 14:40 от Алексей1153 » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 09-09-2021 20:43 » 

Что там повторно определяется и где? Я такого не встречал. Обе библиотеки можно использовать совместно. Спутал с LL, с SPL все возможно.

Леш, там чистый С. Компиляторы разные, в зависимости от среды, но как минимимум C99 поддерживается.
Особенность embedded разработки в том, что нароют древние библиотеки или старый проект и пытаются скрестить с современной средой, а не прет.
« Последнее редактирование: 09-09-2021 20:48 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 10-09-2021 03:49 » 

RXL, если чистый Си - то сам Страуструп велел в разные cpp заинклудить и наружу пробросить по плюснутому ) Оно взлетит. Сомневаюсь, что там в исходниках C11-е несовместимости с C++ - м  встретятся, если проекты древние Улыбаюсь

Добавлено через 3 минуты и 41 секунду:
мне если попадается код на Си, но при этом мне необходимо его заюзать - я только так и поступаю, без всяких экспериментов. Потому что там обязательно каша будет

Добавлено через 58 секунд:
ещё "забавно" бывает по ним статическим анализатором пройтись, сразу волосы дыбом Отлично
« Последнее редактирование: 10-09-2021 03:54 от Алексей1153 » Записан

Boriska
Помогающий

ua
Offline Offline

« Ответ #4 : 10-09-2021 06:23 » 

Ну не совсем так. Библиотека таки SPL и HAL. LL я еще не смотрел. Написаны они на С. Но в среде можно подключить С++, для пользовательских нужд.
Цитата
Что там повторно определяется и где?
.
Ну вот пример повторного typedef
Код:
Error[Pe256]: invalid redeclaration of type name "GPIO_InitTypeDef" (declared at line 148 of "H:\STM\Projects\Projects\IAR\First\SPL\inc\ H:\STM\Projects\Projects
\IAR\First\HAL\inc\stm32f4xx_hal_gpio.h 63 stm32f4xx_gpio.h")
с повторным дефайном констант и макроссов я поборолся как писал выше
Цитата
#undef IS_PWR_STOP_ENTRY
#undef IS_GPIO_SPEED
#undef IS_EXTI_LINE
#undef IS_EXTI_MODE
#undef IS_EXTI_TRIGGER
#undef IS_I2S_MCLK_OUTPUT
#undef IS_I2S_AUDIO_FREQ
#undef IS_GPIO_PIN
#undef IS_GPIO_MODE
#undef IS_SPI_MODE
и др....
Как видите это SPL и НAL
Цитата
Особенность embedded разработки в том, что нароют древние библиотеки или старый проект и пытаются скрестить с современной средой, а не прет.
Обижаете поставил Cube с сайта производителя, взял оттуда обе библиотеки, поставил IAR и решил приладить обе и простейшую main.
Вот какой стандарт С++ не указан, С++ и С++ with IAR extentions
« Последнее редактирование: 10-09-2021 06:35 от Boriska » Записан
Boriska
Помогающий

ua
Offline Offline

« Ответ #5 : 10-09-2021 06:34 » 

Алексей
Цитата
Boriska, привет. Включай заголовки разных библиотек исключительно в разные единицы трансляции. Тогда пересечений не будет
можно чуть расширить ответ, как это делается.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 10-09-2021 06:44 » 

Boriska, что-то вроде:

main.cpp
Код: (C++)
int main()
{
}

my_wrapper_SPL.cpp
Код: (C++)
#include .... всё для SPL ....

my_wrapper_HAL.cpp
Код: (C++)
#include .... всё для HAL ....

Добавлено через 1 минуту и 8 секунд:
далее идёт гемор по вкидыванию в main.cpp всего необходимого при помощи extern
(это можно как раз в my_wrapper_SPL.h и my_wrapper_HAL.h разместить, которые нужно включить в остальные cpp)

Добавлено через 4 минуты и 14 секунд:
и, да, каждой библиотеке во вропперах свой namespace полезно будет сделать
« Последнее редактирование: 10-09-2021 06:51 от Алексей1153 » Записан

Boriska
Помогающий

ua
Offline Offline

« Ответ #7 : 10-09-2021 08:37 » 

Алексей++ там же в этих хидерах, рассматривая как дизэблится assert напоролся на такое выражение
Код:
#ifdef  USE_FULL_ASSERT

/**
  * @brief  The assert_param macro is used for function's parameters check.
  * @param  expr: If expr is false, it calls assert_failed function
  *   which reports the name of the source file and the source
  *   line number of the call that failed.
  *   If expr is true, it returns no value.
  * @retval None
  */
  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
  void assert_failed(uint8_t* file, uint32_t line);
#else
  #define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */

собственно  ((void)0); попробовал IAR игнорит, студия VS17 тоже.
под правило раскрутки https://docs.microsoft.com/en-us/cpp/c-language/interpreting-more-complex-declarators?view=msvc-160
не подпадает. Раскрутите ((void)0); на человеческий ?
« Последнее редактирование: 10-09-2021 08:49 от Boriska » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 10-09-2021 10:18 » 

Boriska,

Цитата
(void) выражение;

- всего лишь "делание вид", что неиспользуемый результат выражения используется
то есть, в данном случае - это будет просто ничего не делающий макрос

Добавлено через 1 минуту и 47 секунд:
в C++11 и старше рекомендуется заменять на

Цитата
std::ignore=выражение;
https://en.cppreference.com/w/cpp/utility/tuple/ignore
« Последнее редактирование: 10-09-2021 10:22 от Алексей++ » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 10-09-2021 21:13 » 

Попробую еще раз объяснить суть раздельной компиляции: разные модули (.c файлы) работают только с одной версией системной библиотеки, интерфес библиотек описан в обном или нескольких заголовках (.h файлы), где, как сказал Леха, объявлены только структуры и прототипы функций, причем последние предварены extern, аналогично с глобальными переменными. При компиляции получаются объектые (.o) файлы. Они содержат эспортируемые и импортируемые функции. При линковке объектых файлов в бинарь разные модули предоставляют (экспортируют) свои символы и импортируют чужие. Тут главное, чтобы не было одноименных экспортируемых имен в разных модулях. Т.е. разделение на модули гарантированно разделяет макросы и типы, но ничего не может поделать с функциями. Неэкспортируемые функции объявлены со static, это означает вилимость только внутри модуля.

GPIO_InitTypeDef — это объявление типа через typedef struct. В HAL используется в типе параметра функции.
void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
Раздельная компиляция поможет обойти данную ошибку. Но инициализация GPIO должна быть одна, в одном модуле, а не в нескольких модулях, иначе будет несогласнованность.

Все это очень скользкая дорожка. По хорошему, надо к одной системной библиотеке сводить.

Добавлено через 2 минуты и 55 секунд:
Алексей++, тут не плюсы, все на чистом Си. Не С++99, а С99. Например, в отличии он ANSI С, в C99 менее строгое объявление переменных, не только в начале функции или блока.
« Последнее редактирование: 10-09-2021 21:16 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Boriska
Помогающий

ua
Offline Offline

« Ответ #10 : 24-09-2021 12:22 » 

Привет.
Поясните как вы лихо связали
(void) выражение; с std::ignore=выражение; Плюс там было ((void)0) это ((void)литерал)
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 24-09-2021 12:50 » 

Boriska, это вопрос Лехе?

SPL и HAL делают одно и тоже, просто они созданы в разное время. Я думаю, что нужно погуглить гайд миграции с SPL на HAL и все привести к единой библиотеке.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Boriska
Помогающий

ua
Offline Offline

« Ответ #12 : 24-09-2021 13:29 » 

Народ который давно сидит пользуется или CMSIS или SPL или LL или HAL.  Все тяжелее и тяжелее. Это была моя заморочка иметь под собой все четыре и дергать ту которая нужна мне в проекте для конкретной задачи - как-то хочется простое делать на простой библиотеке допустим CMSIS (на регистрах), а если запись на SD карту, в подробности протокола записи SD карты не вникать и сделать это на HAL.

Ну Лехе не Лехе, а не совсем понятно объяснение.
« Последнее редактирование: 24-09-2021 14:15 от Boriska » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #13 : 24-09-2021 18:19 » 

Boriska, выражение - это какое угодно rvalue-выражение. Приведение неиспользуемого выражения к (void) или присвоение его к std::ignore даёт знать компилятору и анализатору, что тут не требуется выдавать предупреждения о неиспользованной переменной или о выражении, не дающем эффекта

Код: (C++)
#include <iostream>
#include <tuple>

[[nodiscard]] int func()
{
    return 1;
}

int main()
{
    func();            //предупреждение
    (void)func();      //ок
    std::ignore=func();//ок
   
    1;            //предупреждение
    (void)1;      //ок
    std::ignore=1;//ок
   

    return 0;
}
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 26-09-2021 20:50 » 

Boriska, в итоге, получилось?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Boriska
Помогающий

ua
Offline Offline

« Ответ #15 : 19-11-2021 08:40 » 

Привет.
Пока отложено (работа пока заедает), но возвращение обязательно (микропроцесоры это для души), и обязательно напишу.
Да, кстати, vs ключи компилятора, как вывести препроцессированный файл.
« Последнее редактирование: 19-11-2021 08:42 от Boriska » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines