Перейти к содержанию
    

Как в модуле Си увидеть функцию, объявленную в другом

Изучаю STM32. Взял пример с сайта STM для STM322xG-EVAL, в котором шина USB используется как виртуальный COMport, и пытаюсь его немного переделать. Хочу, чтоб при нажатии кнопки на клавиатуре контроллер передавал компьютеру в ЦИКЛЕ массив из цифр 1-32, при повторном нажатии- чтоб останавливался. Возникла проблема: когда я пытаюсь организовать передачу из main вызывая функцию VCP_DataТx, то программа не компилируется - пишет либо "функция не определена" при простом вызове VCP_DataTx (), либо "недопустимо двойное определение" - на определение функции как "extern uint16_t VCP_DataTx ();". Функция VCP_DataTx () определена в исходной программе в модуле usbd_cdc_vcp.c . Как правильно поступить в данной ситуации?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

подключить соотвествующий заголовочный файл (там где её прототип, должно называться usbd_cdc_vcp.h)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробовал. Компиляция прошла с предупреждением: warning: #223-D: function "VCP_DataTx" declared implicitly. А линковщик выдал ошибку:

Error: L6218E: Undefined symbol VCP_DataTx (referred from app.o). Это можно обойти?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В файле usbd_cdc_vcp.c функция VCP_DataTx определена как static. Поэтому ее нельзя использовать в другом модуле, уберите static в объявлении и тогда можно будет подцепить ее в другом модуле.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Меня смущает определение "static". Наверно, при написании программы его ввели с определённой целью. Если я его уберу, то не появятся новые "косяки"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Весьма странно. Нет ли на VCP_DataTx() модификатора static?

Надо бы проект выложит сюда.

 

__

упс, уже опередили.

косяки не появятся, static нужен для того, чтобы отрубать доступ к функции вне единицы трансляции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Меня смущает определение "static". Наверно, при написании программы его ввели с определённой целью. Если я его уберу, то не появятся новые "косяки"?
Исходников не видел, но ваши рассуждения кажутся мне очень и очень логичными. Отсюда следует вывод - для передачи данных из вашего, пользовательского кода предусмотрена другая функция. И вам надо ее найти.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Отсюда следует вывод - для передачи данных из вашего, пользовательского кода предусмотрена другая функция.

Не предусмотрена. Этот пример - банальный переходник USB-UART. Указанная функция вызывается из прерывания по RXNE и берет данные из UART, что бы передавать ей свои данные ее нужно слегка переписать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не предусмотрена.

...

чтобы передавать ей свои данные ее нужно слегка переписать.

Значит это пример того, как не надо писать программы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Иногда полезно обращаться к первоисточникам: почитал про то, как определяются функции, переопределил VCP_DataTx() как extern (вместо static) в модуле usbd_cdc_vcp.c , и всё прекрасно увиделось из модуля app.c ( из main). Может кому пригодится этот опыт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что это за первоисточник такой? Если в объявлении функции отсутствует спецификатор класса памяти, то по умолчанию принимается класс extern. Вам написали, что надо сделать заголовочный файл в котором перечислить прототипы функций, которые вы хотите использовать не только в текущем исходном файле, и уже подключать это заголовочный файл к другим исходным файлам (это все с условием что нет static)

Заголовочный файл

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я далеко не специалист в программировании, и не особо настаиваю на правильности того, что написал. Может, это совсем неправильно с точки зрения программирования на Си. Просто на практике так сделал - и заработало, без сбоев и тормозов.

Сведения же я взял так : набрал в яндексе "static в си" и первая ссылка оказалась helloworld.ru›texts/comp/lang/c/c/h16.htm .

Там и прочитал следующее :

"Спецификатор класса памяти в объявлении переменной может быть auto, register, static или extern. Если класс памяти не указан, то он определяется по умолчанию из контекста объявления. " и далее

"При объявлении переменной на внутреннем уровне может быть использован любой из четырех спецификаторов класса памяти, а если он не указан, то подразумевается класс памяти auto. "

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

переопределил VCP_DataTx() как extern (вместо static) в модуле usbd_cdc_vcp.c , и всё прекрасно увиделось из модуля app.c ( из main).
Если автор программы определил в модуле функцию как static, это значит, что он не предполагал, что этой функцией будут пользоваться снаружи модуля. Когда вы сделали ее extern, до нее стало можно добраться и снаружи, но намерения первоначального автора модуля при этом не изменились :rolleyes:

Так что позвать вы ее (функцию) теперь можете, но последствия этого вызова целиком на вашей совести.

 

 

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Точно, на такие грабли я уже наступал. Спасибо за напоминание.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...