Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Перенос кода в среду IAR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК
Василий Зыков
Добрый день, коллеги!
Переношу проект, написанный в AVR Studio 4 под WinAvr, в среду IAR
Столкнулся с тем, что IAR ругается на такую конструкцию (ошибка Pe513):

ssp.spiHwInit=(void *)atmega_spi_init;

где объявления даны следующим образом:

euint8 atmega_spi_init(atmegaSpiInterface *iface);

и
Код
struct SdSpiProtocol
{
    void *spiHwInterface;
    euint8 (*spiHwInit)(void* spiHwInterface);
    euint8 (*spiSendByte)(void* spiHwInterface,euint8 data);
};
typedef struct SdSpiProtocol SdSpiProtocol;
Подскажите, пожалуйста, как ее правильно описать в IAR?
scifi
Очевидно, компилируете в режиме Си++. Не надо так делать. Пусть будет просто тёплый ламповый Си.
Василий Зыков
Цитата(scifi @ Mar 14 2017, 14:46) *
Очевидно, компилируете в режиме Си++. Не надо так делать. Пусть будет просто тёплый ламповый Си.

Да нет, проверил, в настройках стоит С. C dialect C99
scifi
Цитата(Василий Зыков @ Mar 14 2017, 12:53) *
Да нет, проверил, в настройках стоит С. C dialect C99

А, не заметил, что, очевидно, указатель на функцию приводите к void* и присваиваете другому указателю на функцию. Это безобразие. Если какой-то компилятор такое проглатывал, то это неправильный компилятор.
Можно сделать вот так:
Код
ssp.spiHwInit=(euint8 (*)(void*))atmega_spi_init;

Но необходимость приведения типа указателя на функцию настораживает, конечно. Кто придумал всё это безобразие?
Василий Зыков
Цитата(scifi @ Mar 14 2017, 15:10) *
А, не заметил, что, очевидно, указатель на функцию приводите к void* и присваиваете другому указателю на функцию. Это безобразие. Если какой-то компилятор такое проглатывал, то это неправильный компилятор.
Можно сделать вот так:
Код
ssp.spiHwInit=(euint8 (*)(void*))atmega_spi_init;

Но необходимость приведения типа указателя на функцию настораживает, конечно. Кто придумал всё это безобразие?


Winavr такое проглатывает..... другой разработчик давно написал этот код. Работало и работало. Пока не появилась необходимость что-то поменять.

Спасибо огромное! Заработало! Только... теперь я не понимаю, как эта конструкция построена. Так сложно на первый взгляд. Спасибо еще раз!
Почему-то без приведения типа компилятор тоже выдает ошибку... меня это тоже смущает.
scifi
Цитата(Василий Зыков @ Mar 14 2017, 13:55) *
теперь я не понимаю, как эта конструкция построена. Так сложно на первый взгляд.

Приведение к типу "указатель на функцию". Ну да, с непривычки странно выглядит.

Цитата(Василий Зыков @ Mar 14 2017, 13:55) *
Почему-то без приведения типа компилятор тоже выдает ошибку... меня это тоже смущает.

Надо смотреть, какой тип у ssp.spiHwInit. Очевидно, какой-то другой, раз компилятор жалуется без приведения типа.
SSerge
Цитата(scifi @ Mar 14 2017, 18:35) *
Надо смотреть, какой тип у ssp.spiHwInit. Очевидно, какой-то другой, раз компилятор жалуется без приведения типа.

Так в первом сообщении всё есть.
Поле в структуре описано как указатель на функцию, принимающую указатель на void и возвращающую euint8,
а ему пытаются присвоить указатель на функцию, принимающую указатель на atmegaSpiInterface и возвращающую euint8.
Ясное дело, без явного преобразования типа такое делать нельзя, и преобразование к типу void* не поможет.
Вот если наоборот - полю типа void* можно присваивать любой указатель. Но тогда для вызова функции по такому указателю потребуется преобразование его типа в тип, соответствующий вызываемой функции, что открывает массу возможностей для ошибок.

Вообще, передача в функции указателей на структуры и наличие в структурах указателей на функции верный признак того, что рамки С коду уже тесны и пора переходить на С++, а не заниматься имитацией на С классов и виртуальных функций.
aiwa
Цитата(Василий Зыков @ Mar 14 2017, 12:55) *
Только... теперь я не понимаю, как эта конструкция построена. Так сложно на первый взгляд.


Более наглядная конструкция:
*((void**)&ssp.spiHwInit) = (void*)atmega_spi_init;

scifi
Цитата(aiwa @ Mar 14 2017, 16:52) *
Более наглядная конструкция:
*((void**)&ssp.spiHwInit) = (void*)atmega_spi_init;

Так это же совсем другая семантика. Не будет работать, короче.
aiwa
Цитата(scifi @ Mar 14 2017, 16:05) *
Так это же совсем другая семантика. Не будет работать, короче.

Зависит от модели памяти: требуется совпадение физических размеров "DATA pointer" и "FUNC pointer", тогда будет работать.
Но пример приведен как альтернатива для понимания.
Правильно будет использовать Ваш вариант приведения.
scifi
Цитата(aiwa @ Mar 14 2017, 18:29) *
Но пример приведен как альтернатива для понимания.

Что-то я в звёздочках запутался. Вроде бы должно и эдак получиться laughing.gif
Василий Зыков
Спасибо большое вам за комментарии и разъяснения!

Цитата(aiwa @ Mar 14 2017, 18:52) *
Более наглядная конструкция:
*((void**)&ssp.spiHwInit) = (void*)atmega_spi_init;


Нет, пожалуй, первая конструкция мне понятнее sm.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.