c - __attribute__((weak)) 不适用于多个目标文件

标签 c gcc

我可能对 weak 理解有误:

我的情况:

  1. 具有一些弱回调的“物理层”
  2. 实现这些回调的“框架层”,并为应用层提供新的 WEAK 回调
  3. 主要 - 应用层。

phy.h

#pragma once

void phyStuff(void);

// new callback for higher layer
void __attribute__((weak)) phy_cb();

phy.c

#include <stdlib.h>
#include <stdio.h>
#include "phy.h"

// Callback, weak
void phy_cb() {
    printf("phy_cb, default implementation. BAD!!!\n");
}    

void phyStuff(void) {
    printf("PHY stuff. Running phy_cb.\n");
    phy_cb();
}

frm.h

#pragma once
#include "phy.h"

void frmStuff(void);

// new callback for higher layer
void __attribute__((weak)) frm_cb();

frm.c

#include <stdio.h>    
#include "phy.h"
#include "frm.h"

// implement the callback
void phy_cb() {
    printf("phy_cb, FRM implementation. GOOD\n");
}    

// Callback, weak
void frm_cb() {
    printf("frm_cb, default implementation. BAD!!!\n");
}    

void frmStuff(void) {
    printf("FRM stuff. Running frm_cb\n");
    frm_cb();
}

ma​​in.c

#include <stdio.h>

#include "frm.h"
#include "phy.h"

void frm_cb() {
    printf("frm_cb, APP implementation. GOOD\n");
}

void main(void) {
    printf("Main.\n");

    phyStuff();
    frmStuff();
}

现在,如果我编译它...

$ gcc main.c phy.c frm.c
$ ./a.out 
Main.
PHY stuff. Running phy_cb.
phy_cb, default implementation. BAD!!! <--- not expected!
FRM stuff. Running frm_cb
frm_cb, APP implementation. GOOD

为什么在这种情况下没有覆盖弱符号?有什么解决方法吗?

最佳答案

您应该将 __attribute__((weak)) 应用于实现,而不是原型(prototype):

phy.h

#pragma once

void phyStuff(void);

// new callback for higher layer
void phy_cb();

phy.c

#include <stdlib.h>
#include <stdio.h>
#include "phy.h"

// Callback, weak
__attribute__((weak)) void phy_cb() {
    printf("phy_cb, default implementation. BAD!!!\n");
}    

void phyStuff(void) {
    printf("PHY stuff. Running phy_cb.\n");
    phy_cb();
}

frm.h

#pragma once
#include "phy.h"

void frmStuff(void);

// new callback for higher layer
void frm_cb();

frm.c

#include <stdio.h>    
#include "phy.h"
#include "frm.h"

// implement the callback
void phy_cb() {
    printf("phy_cb, FRM implementation. GOOD\n");
}    

// Callback, weak
__attribute__((weak)) void frm_cb() {
    printf("frm_cb, default implementation. BAD!!!\n");
}    

void frmStuff(void) {
    printf("FRM stuff. Running frm_cb\n");
    frm_cb();
}

ma​​in.c

#include <stdio.h>

#include "frm.h"
#include "phy.h"

void frm_cb() {
    printf("frm_cb, APP implementation. GOOD\n");
}

void main(void) {
    printf("Main.\n");

    phyStuff();
    frmStuff();
}

现在我们得到了想要的结果:

$ gcc main.c phy.c frm.c
$ ./a.out 
Main.
PHY stuff. Running phy_cb.
phy_cb, FRM implementation. GOOD
FRM stuff. Running frm_cb
frm_cb, APP implementation. GOOD

为了更好地了解发生了什么,尝试分别编译源文件并查看每个对象中的符号:

$ gcc phy.c -o phy.o -c
$ gcc frm.c -o frm.o -c
$ gcc main.c phy.o frm.o
$ nm phy.o | grep _cb
0000000000000000 W phy_cb
$ nm frm.o | grep _cb
0000000000000010 W frm_cb
0000000000000000 T phy_cb
$ nm a.out | grep _cb
000000000040052d T frm_cb
0000000000400581 T phy_cb

nm 中的“W”表示它是一个符号。

关于c - __attribute__((weak)) 不适用于多个目标文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33397850/

相关文章:

c++ - gcc内联汇编jmp地址;裸函数

c - 在 C : prevent generating stack pointer initialization 中写入引导扇区

c - printf() 和 scanf() float* 变量有多少种方法?

c++ - GCC-Visual Studio std::thread 编译器差异

在 OS X 上使用错误版本的 GCC 构建 Python

c - 从 C 代码构建 AST

c++ - windres fatal error : when writing output to : Invalid argument

c - 如何打印数组中包含的结构元素

c - 三个不同权重的数字的平均值

c++ - 预处理之后和使用 CMake 编译之前的自定义构建步骤