Неправильное использование функции обратного вызова void-выражения - PullRequest
0 голосов
/ 05 октября 2018

Я борюсь с функциями обратного вызова в 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-указатель, требуется две вещи:

  1. объявить f-указатель как параметр в этом первом объявлении f-указателя
  2. фактическая функция, которую вы передаете, должна также объявить f-указатель какпараметр

- когда вы передаете f-указатели, не вызывайте их при передаче.Вызывайте их, когда вам нужно вызвать их, ни в объявлении параметра, ни в вызове.

-Также при передаче нескольких параметров для вызовов, имеющих несколько уровней, помните, что это работает как воронка: вы передаете любойпараметры для функций указателей как отдельный параметр родительского вызова.(отсюда переопределение 'const int * mode', который затем get передается в функцию, ожидающую const int *).Это относится к указателям на несколько уровней в качестве параметров других указателей на функции.

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

Мир.

1 Ответ

0 голосов
/ 05 октября 2018

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

Возьмем, к примеру, эту строку: void dw_SpiSetPolAlpha(void (*gpio_setfn)())

Это объявление функции dw_SpiSetPolAlpha, котораяпринимает в качестве параметра указатель на функцию.На указатель можно ссылаться как gpio_setfn, и он должен указывать на функцию, которая возвращает void и не принимает параметров.

Но в момент, когда вы вызываете dw_SpiSetPolAlpha, вы передаете zg_SetDwSpiPolAlpha(DW_SPI_LPOL_LPHA_MASK), чтовызов функции - поэтому вы передаете void, результат - не саму функцию.

Если вместо этого вы объявите void dw_SpiSetPolAlpha(void (*gpio_setfn)(int)), вы сможете передать указатель на функцию, используя dw_SpiSetPolAlpha(zg_SetDwSpiPolAlpha)и в dw_SpiSetPolAlpha вы можете использовать указатель функции - и фактически вызывать функцию - вызывая gpio_setfn(DW_SPI_LPOL_LPHA_MASK)


Редактирование, используя некоторые typedefs.(Я не делаю это перед компилятором, это не в моей голове, поэтому может потребоваться некоторая настройка ...)

typedef void (*callback)(int);
typedef void (*callback_setter)(callback);

void dw_SpiSetPolAlpha(callback gpio_setfn) {
...
}

void radio_Init(callback_setter radio_spi_polalpha)) {
...
}
...