【问题标题】:What are weak functions and what are their uses? I am using a stm32f429 micro controller什么是弱函数,它们的用途是什么?我正在使用 stm32f429 微控制器
【发布时间】:2016-06-01 03:39:42
【问题描述】:
维基百科说:
弱符号表示链接过程中的特殊注释符号
可执行和可链接格式 (ELF) 对象文件。默认情况下,没有
任何注释,目标文件中的符号都是强的。在链接过程中,
强符号可以覆盖同名的弱符号。在
相反,共享名称的两个强符号会产生链接错误
在链接时间。链接二进制可执行文件时,弱声明
符号不需要定义。相比之下,(默认情况下)a
没有定义的声明强符号触发未定义
符号链接错误。 C 或 C++ 语言未提及弱符号
标准;因此,将它们插入代码不是很便携。
即使两个平台支持相同或相似的标记语法
符号很弱,语义可能在细微之处有所不同,例如
运行时动态链接期间的弱符号是否丢失
语义与否。
什么是弱函数,它们的用途是什么?我正在使用 stm32f429 微控制器。库中有一些弱函数。但我不明白,它们和它们的用途!
我在谷歌上搜索过,但没有得到满意的答案。
【问题讨论】:
标签:
c
stm32f4discovery
stm32f4
stm32ldiscovery
【解决方案1】:
当一个函数前面带有 __weak 描述符时,它基本上意味着如果你(编码器)不定义它,它就在这里定义。
让我们看看我的宿敌“HAL_UART_RxCpltCallback()”。
此函数存在于您可以从 ST-Micro 下载的 STM32F4-HAL 代码库的 HAL 中。
在文件stm32f4xx_hal_uart.c文件中你会发现这个函数定义为:
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_RxCpltCallback could be implemented in the user file
*/
}
因此,正如此处代码中的注释所说,将此函数放在您自己的用户文件中。但是,当您这样做时,请不要输入 __weak 术语。这意味着链接器将采用您对 HAL_UART_RxCpltCallback() 函数的定义,而不是在 stm32f4xx_hal_uart.c 文件中定义的函数。
这使通用代码库能够始终编译。您不必编写一大堆您不感兴趣的函数,但它会编译。在编写自己的代码时,您只需不要将自己的代码定义为 __weak 并编写它。
简单吗?有用吗?
干杯!!
【解决方案2】:
__weak 函数是可以被同名用户函数覆盖的方法,用于定义向量表和默认处理程序
普通函数编写(声明和定义)被认为是强函数名,不能重新声明函数名,你会得到编译器/链接器错误
将函数声明为可以被用户代码覆盖的星期
void USART1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
uint32_t vectors[75] __attribute__((section(".isr_vector")));
vectors[0] = STACK_START;
vectors[52] = USART1_IRQHandler;
void Default_Handler(void) {
while(1);
}
uart1.c (user code)
void USART1_IRQHandler(){
...
}
在上面的示例代码中,USART1_IRQHandler 被定义为弱函数并别名为 Default_handler
如果用户在 uart1.c 中定义 USART1_IRQHandler,则用户可以使用相同的名称覆盖此函数而不会出现任何编译器/链接器错误,将使用此新函数定义
【解决方案3】:
除了“这使通用代码库能够始终编译”。 __weak 允许您重新生成(在 CubeMX 中)您的代码,而无需触及您的 __weak +less 回调函数代码。
如果您在此编写代码:
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_RxCpltCallback could be implemented in the user file
*/
}
并出于某种原因在 cubemx 中重新生成。你的代码会爆炸!
【解决方案4】:
假设我们有一个通用(库)协议接口protocol.c,并且在接收到数据后,我们希望在我们的通信接口com.c 中执行特定于应用程序的逻辑。这可以通过弱函数来解决。
/// protocol.h
void protocol_recCallback(protocol_t *prt);
/// protocol.c
__weak void protocol_recCallback(protocol_t *prt) {}
void protocol_rx(protocol_t *prt)
{
// Common protocol interface
protocol_recCallback(prt); // This will call application specific function in com.c
}
/// com.c
#include "protocol.h"
void protocol_recCallback(protocol_t *prt)
{
// Application specific code is executed here
}
优势:
如果protocol_recCallback() 未在com.c 中定义。链接器不会输出未定义的引用,__weak 函数将被调用。