什么是弱函数,它们的用途是什么?我正在使用 stm32f429 微控制器

Posted

技术标签:

【中文标题】什么是弱函数,它们的用途是什么?我正在使用 stm32f429 微控制器【英文标题】:What are weak functions and what are their uses? I am using a stm32f429 micro controller 【发布时间】:2016-06-01 03:39:42 【问题描述】:

***说:

弱符号表示链接过程中的特殊注释符号 可执行和可链接格式 (ELF) 对象文件。默认情况下,没有 任何注释,目标文件中的符号都是强的。在链接过程中, 强符号可以覆盖同名的弱符号。在 相反,共享名称的两个强符号会产生链接错误 在链接时间。链接二进制可执行文件时,弱声明 符号不需要定义。相比之下,(默认情况下)a 没有定义的声明强符号触发未定义 符号链接错误。 C 或 C++ 语言未提及弱符号 标准;因此,将它们插入代码不是很便携。 即使两个平台支持相同或相似的标记语法 符号很弱,语义可能在细微之处有所不同,例如 运行时动态链接期间的弱符号是否丢失 语义与否。

。库中有一些弱函数。但我不明白,它们和它们的用途!

我在谷歌上搜索过,但没有得到满意的答案。

【问题讨论】:

【参考方案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 函数将被调用。

【讨论】:

以上是关于什么是弱函数,它们的用途是什么?我正在使用 stm32f429 微控制器的主要内容,如果未能解决你的问题,请参考以下文章

元表是如何工作的,它们的用途是啥?

框架助手,它们的用途是什么?

PHP 构造函数的用途

在学STM32的USART1,用Printf函数向超级终端打印信息。为啥超级终端没有反应?求帮助。

Kotlin 中这些东西的用途是啥?

Python3 的“函数注释”有啥好的用途?