无效使用void表达式回调函数

时间:2018-10-05 12:20:16

标签: c callback embedded function-pointers

我在用C语言的回调函数苦苦挣扎。

基本上,我正在尝试编写一些中间件来证明概念。我正在使用Silabs的32位零壁虎和Decawave的UWB无线电模块。

我正在尝试在考虑模块化的情况下开发此代码。我想将其与所选的主机系统和无线电分离。我要用于此的另一个项目是wifi模块,即使使用UWB模块进行POC,我也不会使用零壁虎。

无论哪种方式,我都试图将HAL与中间件分离,然后调用两个HAL的任何所需组合。

gpio功能是必需的,因为在加电时断言所需的线路会像其他无线模块一样设置spi极性和alpha。

中间件层:

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();

}

主机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表达式”

我不明白,因为我所有的函数都是无效的返回类型。

我鬼混了一下,尝试了一下:

UWB 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);

 }

但是我只得到一个隐式声明错误

如果这是重复的话,我深表歉意,但我已尽我最大的努力研究了有关此问题的尽可能多的线索,但似乎没有人回答我的问题,或者我错过了一些重要的线索。研究的线程如下:

Error invalid use of void expression

Error: invalid use of void expression

"Error: invalid use of void expression" when using function as parameter of another[duplicate]

How do you pass a function as a parameter in 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

不!

 <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 *模式',然后将其传递给期望const int *的函数)。这适用于多个级别的功能指针,作为其他功能指针的参数。

这些事情只不过是语法错误,只是想当您声明并调用此非常有用的,但最初令人困惑的语言功能时,我会分享一些简单的陷阱。

和平。

1 个答案:

答案 0 :(得分:1)

您在尝试传递函数指针时遇到一些问题。看起来您正在传递函数调用的结果,而不是传递函数本身。

以下面这一行为例: 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)

来实际调用函数

使用一些typedef进行编辑。 (我不是在编译器之前执行此操作,这太难了,因此可能需要进行一些调整...)

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

void dw_SpiSetPolAlpha(callback gpio_setfn) {
...
}

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