Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Одна процедура - два имени
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
SasaVitebsk
При создании библиотек (для собственных нужд) столкнулся с проблемкой.

Представьте что делаются две библиотеки для одной и той же задачи. Например, софтовое исполнение и аппаратное. Соответственно все подпрограммы делаются с одинаковыми именами. Для того, чтобы вызывающая прога не видела разницы. Не знала вообще что за библиотека подсунута.

В одной из библиотек есть 2 ф-ции.

Код
void a(int x, int y);
void b(int x, int y);


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

Код
void b(int x, int y)
{
   a(x,y);
}


Компилятор при этом честно генерит:
Код
b: rcall a
    ret


И никакая оптимизация не помогает.
Макроопределениями пользоваться нехочу. Как сделать чтобы компилятор вместо вызова одной подставлял обращение к другой. Фактически, чтобы он сделал бы две метки (при компиляции программы) на одну процедуру?
rezident
Пользуйтесь вызовом функции по указателю. Чтобы вызвать ту или другую функцию достаточно сменить значение указателя.
P.S. правда этот способ ведет к небольшому увеличению расхода памяти, т.к. для указателя нужна переменная.
Сергей Борщ
Цитата(SasaVitebsk @ Mar 10 2008, 01:40) *
Фактически, чтобы он сделал бы две метки (при компиляции программы) на одну процедуру?
Может не на этапе компиляции, а на этапе линковки указывать -Db=a?
SasaVitebsk
Цитата(rezident @ Mar 10 2008, 04:02) *
Пользуйтесь вызовом функции по указателю. Чтобы вызвать ту или другую функцию достаточно сменить значение указателя.
P.S. правда этот способ ведет к небольшому увеличению расхода памяти, т.к. для указателя нужна переменная.

В книге по Си, которой я пользуюсь нет вообще описания работы с указателями на ф-ции. Я уже сталкивался с такими вещами в разных библиотеках. Пользовался и сам, так как это стандартная в общем то вещь во многих языках. Но хотелось бы всётаки почитать где-нибудь вразумительно. Желательно с примерами использования.

Не подскажите где?
DRUID3
Цитата(rezident @ Mar 10 2008, 02:02) *
Пользуйтесь вызовом функции по указателю. Чтобы вызвать ту или другую функцию достаточно сменить значение указателя.
P.S. правда этот способ ведет к небольшому увеличению расхода памяти, т.к. для указателя нужна переменная.

Стойте, я в этом не разобрался и для себя хочу уяснить, это же не C++ и расход будет далеко не только на указатель. А функция альтернативная где будет лежать? Если есть массив указателей и обращение только к одной из них поймет ли компилятор, что вторую не нужно помещать во флешь? Даже если в программе обращение только к одной. А если и поймет - то каждый ли? Где это стандартизированно?

To: SasaVitebsk
по-моему Страуструп сказал, что внутри С++ живет особый язык которым и нужно пользоваться, т.е. не сочетать все его механизмы как попало, ибо это далеко не то, что заложил в него его создатель. Так и к C это подходит. Зачем так усложнять простые вопросы? Я бы пользовался препроцессором. Ну а может Вам применить стандартные шаблоны С++ - это вобщем-то то что Вы хотите, только в нужном месте и в нужное время. Кстати, помнится когда-то GCC C++ генерил сначала кодс C, вот интересно как там выглядели шаблоны. Может это можно найти в каких-то старинных манускриптах по GCC.
Baser
Цитата(SasaVitebsk @ Mar 10 2008, 01:40) *
При создании библиотек (для собственных нужд) столкнулся с проблемкой....
Немного не понятно, вы хотите, чтобы обе библиотеки одновременно присутствовали во флеши и выбирались софтовым переключателем или на этапе линковки подставлялась одна из двух?

Цитата(DRUID3 @ Mar 10 2008, 10:40) *
Если есть массив указателей и обращение только к одной из них поймет ли компилятор, что вторую не нужно помещать во флешь? Даже если в программе обращение только к одной. А если и поймет - то каждый ли? Где это ?
Стандартизированно это или нет не знаю, но обычно хороший компилятор не линкует те модули, к которым нет обращений. Наоборот, всегда есть расширения, которые позволяют принудительно прилинковать такие модули. Например в ИАР это: __root
SasaVitebsk
Цитата(Baser @ Mar 10 2008, 15:13) *
Немного не понятно, вы хотите, чтобы обе библиотеки одновременно присутствовали во флеши и выбирались софтовым переключателем или на этапе линковки подставлялась одна из двух?


Всё проще.

Представляем что есть несколько процедур вызываемых из головы
А
В
С
Д
Программа в голове написана и работает. При чём не имеет значения какую именно библиотеку я подключу. Реализации одинаковы.

Теперь о библиотеках.
В одной библиотеке
Полностью реализованы А,В,Д а функция С ничем не отличается от B
Дабы сохранить совместимость я пишу

void C(void)
{
B();
}

И компилятор честно компилит мне
C:
rcall B
ret

Мне это не совсем понятно. На асме я бы сделал следующим образом

С:
B:
.....
ret

Ну и конструкция
rcall
ret
тоже вызывает у меня непонятки. Я бы на асме написал
rjmp


Включена максимальная оптимизация по скорости! Соптимизировать такие участки - это же пару пустяков и реальный выигрыш. С чем это связано?
zltigo
Цитата(SasaVitebsk @ Mar 10 2008, 02:40) *
Макроопределениями пользоваться нехочу.

Совершенно зря, для 'C', это совершенно нормальное, естественное и правильное решение.
Код
void aa(int x, int y);
void bb(int x, int y);

#define a(x, y) aa( (x), (y) )
#define b(x, y) aa( (x), (y) )

Какие проблемы?
Baser
Я тоже не понимаю причину отказа от препроцессора. Единственный #define решает проблему:

#define C B

laughing.gif
Сергей Борщ
Цитата(SasaVitebsk @ Mar 14 2008, 22:23) *
И компилятор честно компилит мне
C:
rcall B
ret

Мне это не совсем понятно. На асме я бы сделал следующим образом

С:
B:
.....
ret
Попробуйте все же линкеру определить новый символ и присвоить ему адрес имеющейся процедуры, добаваив в скрипт или командную строку -DC=B. Вы получите именно желаемое - метку С с таким же адресом, что и B.

Препроцессор, я так понимаю, вам не нравится потому что хотите подключать к проекту уже скомпилированные библиотеки? Насколько мне известно, многие, кто пытался идти таким путем, приходили в конце концов к включению исходников библиотеки в проект. А в борьбе с путаницой хорошо помогает система контроля версий (svn, bazaar, cvs и т.д.)
SasaVitebsk
Цитата(Сергей Борщ @ Mar 15 2008, 02:34) *
Препроцессор, я так понимаю, вам не нравится потому что хотите подключать к проекту уже скомпилированные библиотеки?


smile.gif

Да нет. Просто не додумался до варианта, предложенного zltigo. smile.gif
А представлял вариант, предложенный Baser. Он - не подходит.

Спасибо также и вам, Сергей Борщ. Возможно где-то такое решение мне пригодится.

Короче на один вопрос, сразу несколько готовых решений. Спасибо большое. smile.gif
meister
Цитата(SasaVitebsk @ Mar 10 2008, 02:40) *
В другой библиотеке обе ф-ции выполняются с помощью одной, поэтому в реализации написано так

Код
void b(int x, int y)
{
   a(x,y);
}


Компилятор при этом честно генерит:
Код
b: rcall a
    ret


И никакая оптимизация не помогает.
Макроопределениями пользоваться нехочу. Как сделать чтобы компилятор вместо вызова одной подставлял обращение к другой. Фактически, чтобы он сделал бы две метки (при компиляции программы) на одну процедуру?


Разместите реализацию b в заголовочном файле и оптимизатор должен справиться. Когда b станет большая - ее оттуда можно будет убрать.

PS
Если бы была глобальная оптимизация, то такое само бы получилось, но она есть далеко не у всех.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.