Я борюсь с функциями обратного вызова в C.
В основном я пытаюсь написать некоторое промежуточное программное обеспечение для подтверждения концепции.Я использую 32-битный геккон нулевого уровня от Silabs, с UWB радиомодулем от Decawave.
Я пытаюсь разработать этот код с учетом модульности.Я хочу отделить его как от хост-системы, так и от радио.Другой проект, для которого я хочу использовать это модуль Wi-Fi, и я не буду использовать нулевого геккона даже после POC с модулем UWB.
В любом случае, я пытаюсь отделить HAL от промежуточного программного обеспечения и затем вызвать любую желаемую комбинацию двух HAL.
Функция gpio необходима, потому что назначение требуемых линий при включении питания устанавливает полярность spi и альфа, как и другие беспроводные модули.
Уровень промежуточного программного обеспечения:
void radio_Init(void (*radio_spi_polalpha)()){
radio_spi_polalpha();
}
UWB HAL:
/* callback for radio_Init()*/
void dw_SpiSetPolAlpha(void (*gpio_setfn)()){
//call to GPIO lower-level fn
gpio_setfn();
}
Host HAL:
/* callback for dw_SpiSetPolAlpha()*/
void zg_SetDwSpiPolAlpha(const int mode){
switch (mode){
case 0: gpio->P[PORTC].DOUTSET |= DW_SPI_LPOL_LPHA_MASK;
break;
case 1: gpio->P[PORTC].DOUTSET |= DW_SPI_LPOL_HPHA_MASK;
break;
case 2: gpio->P[PORTC].DOUTSET |= DW_SPI_HPOL_LPHA_MASK;
break;
case 3: gpio->P[PORTC].DOUTSET |= DW_SPI_HPOL_HPHA_MASK;
break;
}
}
Вызов прикладного уровня:
radio_Init(dw_SpiSetPolAlpha(zg_SetDwSpiPolAlpha(DW_SPI_LPOL_LPHA_MASK)));
Но все, что я получаю, это "недопустимое использование выражения void"
Я не понимаю, хотя, потому что все мои функции являются типами возврата void.
Я немного дурачился и попробовал это:
СШП HAL:
/* callback for radio_Init()*/
void dw_SpiSetPolAlpha(void (*gpio_setfn)(int)){ <-- add int as parameter
//call to GPIO lower-level fn
gpio_setfn();
}
но затем я получаю "слишком мало аргументов для gpio_setfn", которые я затем попытался передать в аргументе gpio_setfn () примерно так:
gpio_setfn(int);
но я просто получаю "ожидаемое выражениеперед int "
и я попытался:
/* callback for radio_Init()*/
void dw_SpiSetPolAlpha(void (*gpio_setfn)(int mode)){ <-- add int as parameter
gpio_setfn(mode);
}
, но я просто получаю неявную ошибку объявления
Я прошу прощения, если это дубликат, но я приложил все усилияпросмотреть как можно больше тем по этому вопросу, но ни один из них не отвечает на мой вопрос, или я пропустилЯ имею в виду жизненно важную подсказку.Исследованы темы:
Ошибка неверного использования пустого выражения
Ошибка: неправильное использование пустого выражения
«Ошибка: недопустимое использование пустого выражения» при использовании функции в качестве параметра другого [дубликата]
Как передать функцию в качестве параметра в C
Я понимаю концепцию функций обратного вызова, поэтому я хочу использовать их для достижения развязки.Если бы кто-то мог дать некоторые разъяснения относительно того, где я ошибся, я был бы очень благодарен.
Спасибо
[ОКОНЧАТЕЛЬНОЕ РЕДАКТИРОВАНИЕ С РЕШЕНИЕМ]: завершено обновление:
Прежде всего, спасибо вам, ребята, еще раз за помощь.(Я закончу с typedef'ом в рефакторе, мне придется постоянно переопределять тип, который раздражает)
Вот законченный код, который работает, как и ожидалось.
хост HAL:
void zg_SetDwSpiPolAlpha(const int* mode){
switch (*mode){
case 0: gpio->P[PORTC].DOUTSET |= DW_SPI_LPOL_LPHA_MASK;
break;
case 1: gpio->P[PORTC].DOUTSET |= DW_SPI_LPOL_HPHA_MASK;
break;
case 2: gpio->P[PORTC].DOUTSET |= DW_SPI_HPOL_LPHA_MASK;
break;
case 3: gpio->P[PORTC].DOUTSET |= DW_SPI_HPOL_HPHA_MASK;
break;
}
}
радио HAL:
void dw_SpiSetPolAlpha(void (*gpio_setfn)(const int*), const int* mode){
//call to GPIO lower-level fn
gpio_setfn(mode);
}
Промежуточное программное обеспечение:
void radio_Init(void (*radio_spi_polalpha)(void (*)(const int*), const
int*), void (*device_gpio_set)(const int*), const int* mode)
{
radio_spi_polalpha(device_gpio_set, mode);
}
Вызов приложения:
const int one = 1;
radio_Init(dw_SpiSetPolAlpha, zg_SetDwSpiPolAlpha, &one);
Несколько замечаний для тех, кто сталкивается с этой проблемой:
- следите за объявлениями f-указателей, особенно когда в качестве параметров: этот бросил меня немного из-за заключенных в скобкиМетка f-указателя.
Функция с параметром:
<return_type> <label>(<f-pointer return_type> (* <label>)( <parameter> )) { } //notice the closing parentheses BEFORE the opening for parameter section. Also note that <label> is optional when declaring a function pointer as a parameter to a function pointer
NOT!:
<return_type><label>(<f-pointer return_type> * <label>(<parameter>)) //similar to expected normal syntax for a function declaration
- передача f-указателя в качестве параметра для f-указатель, требуется две вещи:
- объявить f-указатель как параметр в этом первом объявлении f-указателя
- фактическая функция, которую вы передаете, должна также объявить f-указатель какпараметр
- когда вы передаете f-указатели, не вызывайте их при передаче.Вызывайте их, когда вам нужно вызвать их, ни в объявлении параметра, ни в вызове.
-Также при передаче нескольких параметров для вызовов, имеющих несколько уровней, помните, что это работает как воронка: вы передаете любойпараметры для функций указателей как отдельный параметр родительского вызова.(отсюда переопределение 'const int * mode', который затем get передается в функцию, ожидающую const int *).Это относится к указателям на несколько уровней в качестве параметров других указателей на функции.
Эти вещи - не более чем синтаксические ошибки, но я подумал, что хотел бы поделиться некоторыми простыми ошибками, на которые нужно обратить внимание, когда вы объявляете и называете эту удивительно полезную, но изначально запутывающуюся языковую функцию.
Мир.