void 表达式回调函数的使用无效
Invalid use of void expression callback function
我正在为 C 中的回调函数而苦苦挣扎。
基本上我正在尝试编写一些中间件来验证概念。我使用的是 Silabs 的 32 位零壁虎,以及 Decawave 的 UWB 无线电模块。
我正在尝试在考虑模块化的情况下开发此代码。我想将它与所选的主机系统和无线电分离。我想使用它的另一个项目是一个 wifi 模块,即使通过 UWB 模块的 POC,我也不会使用零壁虎。
无论哪种方式,我都试图将 HAL 与中间件分离,然后调用两个 HAL 的任何所需组合。
gpio 功能是必需的,因为在加电时断言所需线路会设置 spi 极性和 alpha,其他无线模块也是如此。
中间件层:
void radio_Init(void (*radio_spi_polalpha)()){
radio_spi_polalpha();
}
超宽带硬件:
/* 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)));
但我得到的只是"invalid use of void expression"
虽然我不明白,因为我所有的函数都是 void return 类型。
我胡闹了一下,试了一下:
超宽带硬件:
/* callback for radio_Init()*/
void dw_SpiSetPolAlpha(void (*gpio_setfn)(int)){ <-- add int as parameter
//call to GPIO lower-level fn
gpio_setfn();
}
但后来我得到 "too few arguments to gpio_setfn",然后我尝试将参数传递给 gpio_setfn(),如下所示:
gpio_setfn(int);
但我刚得到 "expected expression before int"
我试过了:
/* callback for radio_Init()*/
void dw_SpiSetPolAlpha(void (*gpio_setfn)(int mode)){ <-- add int as parameter
gpio_setfn(mode);
}
但我只是得到一个隐式声明错误
如果这是重复的,我深表歉意,但我已尽我所能浏览尽可能多的关于这个问题的线索,但要么 none 似乎回答了我的问题,要么我错过了一些重要的线索。研究主题如下:
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
我了解回调函数背后的概念,因此我想使用它们来实现解耦。如果有人可以澄清我哪里出错了,我将不胜感激。
谢谢
[带解决方案的最终编辑]:完成更新:
首先,再次感谢你们的帮助。 (我最终会在重构中对它进行类型定义,不得不不断地重新定义类型很烦人)
这是按预期工作的完整代码。
主机 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 指针,需要两件事:
- 在第一个 f 指针声明中将 f 指针声明为参数
- 你传入的实际函数也必须声明一个f指针作为参数
-当你传入 f 指针时,不要在传递它们时调用它们。在需要调用它们时调用它们,既不在参数声明中也不在调用中。
-此外,当为具有多个级别的调用传递多个参数时,请记住它像漏斗一样工作:您将任何参数传递给函数指针作为父调用的单独参数。 (因此重新声明 'const int* mode',然后将其传递到期望 const int* 的函数中)。这适用于多级函数指针作为其他函数指针的参数。
这些东西只不过是语法错误,但只是想分享一些简单的陷阱,以便在您声明和调用这个非常有用但最初令人困惑的语言功能时注意。
和平。
您在尝试传递函数指针时遇到了一些问题。看起来您正在传递函数调用的结果,而不是传递函数本身。
以这一行为例:
void dw_SpiSetPolAlpha(void (*gpio_setfn)())
这是在声明一个函数 dw_SpiSetPolAlpha
,它将一个指向函数的指针作为参数。指针可以被引用为 gpio_setfn
并且它必须指向一个 returns 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 void (*callback)(int);
typedef void (*callback_setter)(callback);
void dw_SpiSetPolAlpha(callback gpio_setfn) {
...
}
void radio_Init(callback_setter radio_spi_polalpha)) {
...
}
我正在为 C 中的回调函数而苦苦挣扎。
基本上我正在尝试编写一些中间件来验证概念。我使用的是 Silabs 的 32 位零壁虎,以及 Decawave 的 UWB 无线电模块。
我正在尝试在考虑模块化的情况下开发此代码。我想将它与所选的主机系统和无线电分离。我想使用它的另一个项目是一个 wifi 模块,即使通过 UWB 模块的 POC,我也不会使用零壁虎。
无论哪种方式,我都试图将 HAL 与中间件分离,然后调用两个 HAL 的任何所需组合。
gpio 功能是必需的,因为在加电时断言所需线路会设置 spi 极性和 alpha,其他无线模块也是如此。
中间件层:
void radio_Init(void (*radio_spi_polalpha)()){
radio_spi_polalpha();
}
超宽带硬件:
/* 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)));
但我得到的只是"invalid use of void expression"
虽然我不明白,因为我所有的函数都是 void return 类型。
我胡闹了一下,试了一下:
超宽带硬件:
/* callback for radio_Init()*/
void dw_SpiSetPolAlpha(void (*gpio_setfn)(int)){ <-- add int as parameter
//call to GPIO lower-level fn
gpio_setfn();
}
但后来我得到 "too few arguments to gpio_setfn",然后我尝试将参数传递给 gpio_setfn(),如下所示:
gpio_setfn(int);
但我刚得到 "expected expression before int"
我试过了:
/* callback for radio_Init()*/
void dw_SpiSetPolAlpha(void (*gpio_setfn)(int mode)){ <-- add int as parameter
gpio_setfn(mode);
}
但我只是得到一个隐式声明错误
如果这是重复的,我深表歉意,但我已尽我所能浏览尽可能多的关于这个问题的线索,但要么 none 似乎回答了我的问题,要么我错过了一些重要的线索。研究主题如下:
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
我了解回调函数背后的概念,因此我想使用它们来实现解耦。如果有人可以澄清我哪里出错了,我将不胜感激。
谢谢
[带解决方案的最终编辑]:完成更新:
首先,再次感谢你们的帮助。 (我最终会在重构中对它进行类型定义,不得不不断地重新定义类型很烦人)
这是按预期工作的完整代码。
主机 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 指针,需要两件事:
- 在第一个 f 指针声明中将 f 指针声明为参数
- 你传入的实际函数也必须声明一个f指针作为参数
-当你传入 f 指针时,不要在传递它们时调用它们。在需要调用它们时调用它们,既不在参数声明中也不在调用中。
-此外,当为具有多个级别的调用传递多个参数时,请记住它像漏斗一样工作:您将任何参数传递给函数指针作为父调用的单独参数。 (因此重新声明 'const int* mode',然后将其传递到期望 const int* 的函数中)。这适用于多级函数指针作为其他函数指针的参数。
这些东西只不过是语法错误,但只是想分享一些简单的陷阱,以便在您声明和调用这个非常有用但最初令人困惑的语言功能时注意。
和平。
您在尝试传递函数指针时遇到了一些问题。看起来您正在传递函数调用的结果,而不是传递函数本身。
以这一行为例:
void dw_SpiSetPolAlpha(void (*gpio_setfn)())
这是在声明一个函数 dw_SpiSetPolAlpha
,它将一个指向函数的指针作为参数。指针可以被引用为 gpio_setfn
并且它必须指向一个 returns 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 void (*callback)(int);
typedef void (*callback_setter)(callback);
void dw_SpiSetPolAlpha(callback gpio_setfn) {
...
}
void radio_Init(callback_setter radio_spi_polalpha)) {
...
}