【问题标题】: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 函数将被调用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-10-24
            • 1970-01-01
            • 2010-12-18
            • 1970-01-01
            • 2010-11-01
            • 2010-12-04
            • 2015-08-07
            • 2010-09-27
            相关资源
            最近更新 更多