|
уникальный идентификатор, как при помощи макросов сформировать уникальный идентификатор |
|
|
|
Mar 27 2009, 11:50
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
собственно, вместо многократного повторения __attribute__ ((naked, section(".init7"))) для разных функций типа void foo(void) в разных файлах хочу сделать какой-то макрос, который сам бы это дело дописал перед каким-то автоматически сгенерированным идентификатором. в общем, пишем: Код initialize{тут код начальной инициализации} а получаем фактически что-то типа Код __attribute__ ((naked, section(".init7"))) void _name120097553(void){nen код начальной инициализации} подскажите, как сделать? ничего путнего не получается... проблема в формировании уникального идентификатора....
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 21)
|
Mar 27 2009, 12:22
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(_Pasha @ Mar 27 2009, 15:17)  Если в файле по одному иниту, их можно обозвать одинаково.  увы, низзя... если функцию не объявлять static - то компоновщик обнаруживает наличие одинаковых идентификаторов... а если объявить static - не действует __attribute__
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Mar 27 2009, 13:07
|
Группа: Участник
Сообщений: 13
Регистрация: 23-10-04
Пользователь №: 968

|
Попробуйте для создания уникальных имен использовать макросы __LINE__ и __FILE__
|
|
|
|
|
Mar 27 2009, 13:24
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(solosh @ Mar 27 2009, 16:07)  Попробуйте для создания уникальных имен использовать макросы __LINE__ и __FILE__ так вот же ж  их и пробовал... проблема в том, что как __LINE__ сконкатировать с символом? если я пишу так: Код #define initialize void init ## __LINE__ (void) то вместо ожидаемого Код void init_234(void) я получаю Код void init___LINE__(void) что неприемлемо...
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Mar 27 2009, 14:25
|
Профессионал
    
Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886

|
Цитата(ARV @ Mar 27 2009, 16:24)  так вот же ж  их и пробовал... проблема в том, что как __LINE__ сконкатировать с символом? если я пишу так: Код #define initialize void init ## __LINE__ (void) то вместо ожидаемого Код void init_234(void) я получаю Код void init___LINE__(void) что неприемлемо... поколдуйте с двойным переопределением. например Код #define MY_LINE __LINE__ #define MY_LINE2 MY_LINE
|
|
|
|
|
Mar 27 2009, 19:31
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(solosh @ Mar 27 2009, 17:16)  Нужен еще один проход препроцессора. Вот как раз Ваш случай: http://electronix.ru/forum/index.php?s=&am...st&p=361393да, случай как раз мой. но почему-то когда я вручную писал static для инициализирующей функции, она исключалась уборщиком мусора (-Wl,-gc-sections -ffunction-sections)... наверное потому, что не было атрибута used? спасибо за помощь!
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Mar 27 2009, 23:38
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
А для чего, простите, весь сыр-бор. Чтобы лишь автоматизировать инициализацию какого-либо программного модуля? Если так, то Вы ребята далеко ушли от программирования на С. Что неужели трудно явно вызывать процедуру инициализации? А как быть с расстановкой очерёдности инициализации разных модулей? С простотой портирования? С наглядностью наконец? На мой взгляд происходит подмена понятия программирования. Извините, но хочется понять глубинный смысл сего явления. Ответ типа: мне удобно т.к. я догадался до такого "извращения" - не то, что хочется услышать  Я сторонник глубинного понимания языка программирования, а не фишек линкера и прочего инструментария, входящего в комплект поставки компилятора. Да это знать и понимать тоже нужно, но использовать так... Уж если считаете, что Вам стал жать С используйте С++ с его конструкторами и деструкторами, шаблонами и всем-всем остальным что Вам будет нужно. Так будет честнее. ИМХО.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Mar 28 2009, 08:57
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(demiurg_spb @ Mar 28 2009, 01:38)  А для чего, простите, весь сыр-бор. Чтобы лишь автоматизировать инициализацию какого-либо программного модуля? Нет, периферии. Цитата(demiurg_spb @ Mar 28 2009, 01:38)  Если так, то Вы ребята далеко ушли от программирования на С. Что неужели трудно явно вызывать процедуру инициализации? Трудно. На каждый вызов положить по ®call/ret и сохранение/восстановление контекста? Нафига? Если для этого есть специально разарботанный очень элегантный механизм.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 28 2009, 10:41
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Сергей Борщ @ Mar 28 2009, 11:57)  Нет, периферии. ... Нафига? Если для этого есть специально разарботанный очень элегантный механизм. Я вас прекрасно понимаю с точки зрения экономии ПЗУ, слабо с точки зрения повышения быстродействия. И совсем никак с моей личной точки зрения. Поясню. У меня обычно пользователю доступны режимы работы устройства (пусть это будет пресловутый UART), так после изменения настроек нужно вызвать процедуру инициализации повторно. Так если эта процедура у меня уже физически есть, то зачем мне всё это? Да есть такая периферия которая не отдаётся на откуп юзеру, так с ней можно и через static inline или __attribute__((always_inline)) "бороться". Хотя тут уже не принципиально как. Спасибо за ответ. Для меня тема исчерпана. Ваш метод имеет право на жизнь  2 ARV: гляньте, тут тоже происходит формирование уникальных идентификаторов: Код #ifdef __cplusplus template<bool> struct CompileTimeError; template<> struct CompileTimeError<true> {}; # define STATIC_ASSERT(expr) (CompileTimeError<(expr) != 0>()) #else # define MY_JOIN_3_H(A,B,C) A##B##C # define MY_JOIN_3(A,B,C) MY_JOIN_3_H(A,B,C) # define STATIC_ASSERT_H(expr) typedef int MY_JOIN_3(static_assert_,__LINE__,_h) [(expr) ? 1 : -1] # define STATIC_ASSERT(expr) STATIC_ASSERT_H(expr) #endif
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Mar 28 2009, 13:43
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Да тут есть свой прикол. Я даже использую это в таком случае: Через makefile спускаю строку (имя файла) в зависимости от типа условной компиляции: Код ADD_COMPILE_FLAGS += -DLOW_LEVELX_H=low_level3.h ... CFLAGS += $(ADD_COMPILE_FLAGS) определяю макрос: Код // str macro #define STR(S) #S // STR(blabla) = "blabla" #define XSTR(S) STR(S) // STR(_version) = "v1.0" if _version = "v1.0" А в программе просто подключаю инклюдом нужный файл без всяких там #if #elif #endif Код #include XSTR(LOW_LEVELX_H) Мне нравится.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Mar 28 2009, 16:50
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(demiurg_spb @ Mar 28 2009, 01:38)  А как быть с расстановкой очерёдности инициализации разных модулей? ... Уж если считаете, что Вам стал жать С используйте С++ с его конструкторами и деструкторами, А что, очерёдность вызовов конструкторов (т.е. инициализации) статических объектов из разных модулей в С++ будет определена? И неужели Вы думаете, что при наличии функции init_XXX(), которая может вызываться по ходу программы в разных местах кто-то будет дублировать её тело в init-блоке? Хотя можно её вызов вставить в Код INIT(8) { init_XXX(); } :-) Cам подход "подключили модуль - он автоматически проинициализируется по умолчанию" имеет право на жизнь, у того же борланда это делалось через #pragma startup/#pragma exit. И дело не только в экономии нескольких байт и тактов, но и в автоматизации того, что можно и нужно автоматизировать, а не нагружать себя самого созданием нагромождения вызовов init_XXX() в начале функции main() (заодно явно видно, какие инициализации терпят перестановку местами, а уж то, что осталось в виде init_XXX() - обкомментировать как и почему оставлено и в каком порядке должно вызываться, если это важно). Ну и кроме того случаи бывают разные, например, может захотеться у той же меги64 или 162 внешнюю память сделать продолжением внутренней и "без дырок" - стек разместить в конце внешней памяти (да, будет работать несколько медленнее, "ну и что"). Тогда включить внешнюю шину надо до первого вызова, даже в С++ с его конструкторами. Вот тогда фрагмент комментария из темы по ссылке выше как раз и поможет. Код * INIT_CODE(1) * { * MCUCR = (1 << SRE); * XMCRA = (4 << SRL0) | (0 << SRW00); * XMCRB = (1 << XMBK); * } static inline тут не поможет. Я таким образом настраиваю всякие таймерные и не только прерывания - рядом с обработчиком ISR() и (если они есть) функциями доступа к разделяемым с прерываниям данными торчит INIT(8), который это всё хозяйство инициализирует. Пусть он себе "вызывается" автоматичекски. Рассматривайте этот метод как расширение возможностей start-up-модуля, но без модификации его текста (чем этот метод и является) и станет понятно, когда его удобно и "правильно" применять. start-up-модуль занимается подготовкй окружения для функции main() (можно було бы ведь в начале функции main() вызывать библиотечные функции clear_bss(); init_initialized_data(); - Вы же не боретесь за право это делать? ) для общго случая, а код в отданных программисту секциях .init1/3/5/7/8 уточняет это для данной конкретной программы.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Mar 28 2009, 20:56
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(demiurg_spb @ Mar 28 2009, 20:54)  Так действительно может оказаться нагляднее и удобнее, нежели править startup.S И отдельное спасибо авторам за раскладку секций: Код * .init0 Start here after reset. * .init1 * .init2 Clear __zero_reg__, set up stack pointer. * .init3 * .init4 Initialize data and BSS. * .init5 * .init6 C++ constructors. * .init7 * .init8 * .init9 Call main() Имеем достаточно мелкую "нарезку" для того, чтобы подсунуть своё именно на нужном этапе. Да, с init1 надо осторожно, если встречается что-то в духе MCUSR = 0; то это надо делать в init3, так как оно будет скомпилировано отправкой в SFR регистра r1, а он обнуляется в init2.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Mar 30 2009, 22:19
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(demiurg_spb @ Mar 28 2009, 17:43)  А в программе просто подключаю инклюдом нужный файл без всяких там #if #elif #endif Код #include XSTR(LOW_LEVELX_H) Мне нравится. C инклюдами можно проще гораздо. Например: Код -DTEST_CFG="\"test1/test_cfg.h\""
#include TEST_CFG // "test1/test_cfg.h"
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|