|
Как правильно создать многофайловый проект, Ошибка при линковке |
|
|
|
 |
Ответов
|
Dec 9 2007, 19:06
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Простите, решил сюда добавить, чтобы темы не плодить. Не так давно пишу на Си. За этот период сильно изменил свои подходы. Теперь проект разбиваю на файлы, которые логически закончены. Это даёт возможность многократного использования с минимальными изменениями. Но вот столкнулся с некоторыми проблемами в таком подходе. В принципе я о них уже читал в разных темах и общие указания слышал/запомнил.
Сама проблема возникает когда п/п из другого файла используется в прерывании, которое в main описывается. Как выходить из неё - вроде понятно. 1) Вообще убрать вызовы п/п. 2) перенести п/п в файл, где пишется прерывание.
Собственно меня интересует более общая тема. Как всётаки сделать так, чтобы и овцы целы и волки сыты. То есть вопросы следующие.
1) Правильным ли является подход с выделением логически законченного блока в отдельный файл со своим хедером. И если "нет" или "не совсем", то хотелось бы услышать как поступают проффессионалы. 2) Как использовать такие "почти библиотеки", чтобы уменьшить накладные рассходы и при этом сохранить красоту написания проги. 3) Является ли выигрышным в этом смысле вариант с С++ и созданием классов/объектов.
|
|
|
|
|
Dec 9 2007, 21:56
|

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

|
Цитата(SasaVitebsk @ Dec 9 2007, 21:06)  п/п из другого файла используется в прерывании, которое в main описывается. Это как? Обычно обработчик прерывания описываю не в main, а в том же файле, что и остальные п/п соответстующего модуля. А зачем обработчик уносить в тот же файл, где и main? Или это архитектера вроде pic, когда одно прервание на все случаи? Плюсы помогут, ибо в них можно в заголовочном файле описать обработчик как inline.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 11 2007, 06:17
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Dec 10 2007, 00:56)  А зачем обработчик уносить в тот же файл, где и main? Это дело вкуса. Я вижу это так. Если железно ясно, что - используется прерывание - и это универсальное решение, то прерывание имеет смысл иметь в модуле, где осуществляется реализация. Если : - хочется иметь main как диспетчер, в котором видна вся логика функционирования - main небольшой по размеру - возможны изменения (без прерывания или с прерыванием), то лучше обработчик прерывания в main. В дальнейшем, когда все устаканится или размер main станет неприличным по размеру, можно его перенести.
|
|
|
|
|
Dec 11 2007, 09:51
|

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

|
Цитата(alexander55 @ Dec 11 2007, 08:17)  Если : - хочется иметь main как диспетчер, в котором видна вся логика функционирования Если это ARM, то в main достаточно заносить адреса обработчиков (объявленных как extern) в нужные регистры контроллера прерываний. Тела самих обработчиков в main() не нужны. Если это проц без контроллера, то у него скорее всего вектора жестко распределены за периферией, и выбор вектора просто однозначен - в main нечего диспетчерить. Если хочется иметь выбор из нескольких одинаковых периферийных модулей (UART, например), то можно попробовать так: Код в Hardware.h указываем #define RS232_MODULE USART1 #define RS485_MODULE USART0
в RS232.c: #pragma RS232_MODULE##_UDRE_vect interrupt void RS232_transmit_handler() {
} //опять main.c не у дел Наконец, если используются плюсы и обработчик - метод класса, то код этого метода с атрибутом inline размещается в заголовочном файле, а в main.cpp пишется "обертка": Код __irq void RS232_Handler() { RS232.Handler(); } или #pragma USART1_UDRE_vect interrupt void RS232_transmit_handler() { RS232.Handler(); } при этом обработчик делается private, а функция-обертка объявляется другом класса. Но при желании эти обертки уносятся в файл соответствующего модуля и можно снова применить первый вариант. Цитата(alexander55 @ Dec 11 2007, 08:17)  В дальнейшем, когда все устаканится или размер main станет неприличным по размеру, можно его перенести. Мне кажется, что всякие методики проектирования создают именно для того, чтобы по возможности исключить такую непроизводительную работу. Хотя, конечно, идеала не существует и процесс был и будет итеративным. Но количество итераций можно попытаться уменьшить.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 11 2007, 10:29
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Dec 11 2007, 12:51)  Наконец, если используются плюсы и обработчик - метод класса, то код этого метода с атрибутом inline размещается в заголовочном файле, а в main.cpp пишется "обертка": Код __irq void RS232_Handler() { RS232.Handler(); } или #pragma USART1_UDRE_vect interrupt void RS232_transmit_handler() { RS232.Handler(); } Я это и имел ввиду. Цитата(Сергей Борщ @ Dec 11 2007, 12:51)  в main нечего диспетчерить. Это не совсем диспетчеризация и даже может совсем не диспетчерезация. Приятно сразу понять логику работы всей системы глядя на один модуль. Детали находятся за рамками и если требуются, то понятно, где это можно посмотреть (глядя на модуль). Второй смысл - это скажем так "просмотр синхронизации потоков и распределенных приложений". Во выдал.
|
|
|
|
|
Dec 11 2007, 13:07
|

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

|
Цитата(alexander55 @ Dec 11 2007, 12:29)  Приятно сразу понять логику работы всей системы глядя на один модуль. У меня в main.c обычно находятся собственно main() и __low_level_init(). Глядя на main() можно попытаться понять логику работы всей системы, правда есть одно исключение  : Код int main() { OS::Run(); } Цитата(alexander55 @ Dec 11 2007, 12:29)  Детали находятся за рамками и если требуются, то понятно, где это можно посмотреть (глядя на модуль). Так RS232_transmit_handler() - это и есть детали. А логика описывается getchar(), putchar() и hasinput(). Мне так кажется... Цитата(SasaVitebsk @ Dec 11 2007, 12:58)  Прерывание - метки времени. То есть там целый набор.  в том числе вызовы опроса клавиатуры. В таком случае наименьшие накладные, наверное, можно получить если "набор" описать в заголовочных файлах как static inline функции.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 11 2007, 13:39
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Dec 11 2007, 16:07)  У меня в main.c обычно находятся собственно main() и __low_level_init(). Глядя на main() можно попытаться понять логику работы всей системы, правда есть одно исключение  : Код int main() { OS::Run(); } Это логичный и устоявшийся модуль. Цитата(Сергей Борщ @ Dec 11 2007, 16:07)  Так RS232_transmit_handler() - это и есть детали. А логика описывается getchar(), putchar() и hasinput(). Мне так кажется... В данном случае так. Цитата(Сергей Борщ @ Dec 11 2007, 16:07)  В таком случае наименьшие накладные, наверное, можно получить если "набор" описать в заголовочных файлах как static inline функции. Или включить максимальную оптимизацию по требуемому параметру.
|
|
|
|
Сообщений в этой теме
alux Как правильно создать многофайловый проект May 6 2007, 14:07 jorikdima хидеры то подключены, а в опциях проекта пути к ни... May 6 2007, 14:20 alux Цитата(jorikdima @ May 6 2007, 17:20) хид... May 6 2007, 14:46  rezident Цитата(alux @ May 6 2007, 20:46) Все файл... May 6 2007, 18:25 andrej2005 Цитата(jorikdima @ May 6 2007, 18:20) хид... Apr 20 2008, 10:34 zltigo Цитата(alux @ May 6 2007, 17:07) void bat... May 6 2007, 14:24 singlskv Цитата(SasaVitebsk @ Dec 9 2007, 22:06) С... Dec 9 2007, 20:22       Сергей Борщ Цитата(alexander55 @ Dec 11 2007, 15:39) ... Dec 11 2007, 15:20 Непомнящий Евгений Просветите плиз - что такое "п/п"? Dec 10 2007, 06:26 Николай Z Цитата(Непомнящий Евгений @ Dec 10 2007, 09... Dec 10 2007, 07:21 Непомнящий Евгений Что такое подпрограмма - я в курсе Просто не сооб... Dec 10 2007, 07:34 SasaVitebsk Я, собственно так и работаю. И думал так все. В с... Dec 11 2007, 10:58 Panych Подниму тему, чтоб не плодить...
Объявляю внешнюю ... Apr 7 2008, 13:32 gotty Цитата(Panych @ Apr 7 2008, 16:32) Подним... Apr 7 2008, 13:45  alux Цитата(gotty @ Apr 7 2008, 16:45) И ещё с... Apr 8 2008, 12:04 Panych gotty
спасибо, сделал функцию внешней, IAR ругнулс... Apr 7 2008, 14:15 MrYuran Цитата(Panych @ Apr 7 2008, 17:15) gotty
... Apr 8 2008, 12:11 ivainc1789 Тема о многостраничных файлах, задам и свой махонь... Apr 9 2008, 15:09 Непомнящий Евгений Цитата(ivainc1789 @ Apr 9 2008, 19:09) Те... Apr 9 2008, 15:51 rezident Цитата(ivainc1789 @ Apr 9 2008, 21:09) Те... Apr 9 2008, 21:55 sKWO Добрый день!
Многофайловый проект, чёрт по....... Apr 13 2008, 10:55 alux Цитата(sKWO @ Apr 13 2008, 13:55) файл dr... Apr 13 2008, 14:08  sKWO Цитата(alux @ Apr 13 2008, 17:08) У вас в... Apr 13 2008, 18:14 Непомнящий Евгений Цитата(sKWO @ Apr 13 2008, 14:55) Кодtype... Apr 14 2008, 04:44  alux Цитата(Непомнящий Евгений @ Apr 14 2008, 07... Apr 14 2008, 06:33
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|