1 gcc attribute weak & alias应用
alias ("target")
The alias attribute causesthe declaration to be emitted as an alias for another symbol, which must bespecified. For instance,
void __f () { /* Do something. */; }
void f () __attribute__ ((weak, alias ("__f")));
defines ‘f’ to be a weakalias for ‘__f’. In C++, the mangled name for the target must be used. It is an error if‘__f’ is not definedin the same translation unit.
Not all targetmachines support this attribute.
这段来自GCC官方文档的说明,其实讲了gcc的alias和weak attribute。
1.1 gcc weak attribute
具体语法,大概和一般gcc属性一样,需要用到__attribtes__((weak))这样的格式。现在我们通过一个例子来说明一下。
1 我们在weak_symbol.c这个文件中声明了一个common_print函数,并且将此函数声明为__attribute__((weak));同时提供了此函数的定义。
//weak_symbol.c #include<stdio.h> voidcommon_print(const char *s) __attribute__((weak));//有weak声明 voidcommon_print(const char *s) { printf("common_print : %s\n",s); }
2 在strong_symbol.c这个文件也定义了common_print函数,需要注意的是此函数在两个不同的c文件中声明、定义的原型都一样的。
//strong_symbol.c #include<stdio.h> voidcommon_print(const char *s) //没有weak声明 { printf("application common_print : %s\n",s); } int main(intargc, char *argv[]) { common_print("I want to test gcc weakattribute"); return 0; }
3 编译连接连个c文件,并且执行的结果如下:
[email protected]:/home/test/gcc_test#./test_weak
applicationcommon_print : I want to test gcc weak attribute
分析:
1) 首先,同样的原型的两个函数在连个不同的c文件中都有定义,把这两个c文件编译、连接在一起,也没有什么错误。原因就是因为,gcc中有一个strong symbol和weak symbol的概念。默认函数定义都是strong symbol的,两个相同的strong symbol连接在一起,肯定会产生”symbol重复定义”的错误。
但是,这里我们将weak_symbol.c中的common_print加了weak属性,这样gcc再选择的时候优先选择strong symbol
2) 其次,根据例子程序执行的结果来看,执行了strong_symbol.c中的common_print函数。如果我们在strong_symbol.c中不提供common_print函数的实现,那么调用的就是weak_symbol.c中的实现。
3) 由上,我们可以想象,当要用c语音提供一个api库的时候,我们可以把这些api都声明为weak属性的,我们可以提供default实现。当用户想要自己定制的时候,也就很容易实现了。glibc中的很多api就是这样设计的。
1.2 gcc weak &alias attribute配合应用的场景
同样,先看一个例子。
1 我们在weak_symbol.c中提供了一个__lib_print函数的实现,同时声明了print_a和print_b两个函数,但是和上面不通的是,这两个函数增加了__attribute__((weak,alias("__lib_print")))熟悉,即print_a和print_b都是__lib_print的别名(alias)。
//weak_symbol.c #include <stdio.h> void __lib_print(const char *s) { printf("__lib_print : %s\n", s); } void print_a(const char *s) __attribute__((weak, alias("__lib_print"))); void print_b(const char *s) __attribute__((weak, alias("__lib_print")));
2 我们在strong_symbol.c中为print_b重新提供了实现,print_a保持默认不变。
//strong_symbol.c #include <stdio.h> void print_b(const char *s) { printf("application print_b : %s\n", s); } int main(int argc, char *argv[]) { print_a("I want to test weak&&alias"); print_b("I want to test weak&&alias"); return 0; }
3 编译连接连个c文件,并且执行的结果如下:
[email protected]:/hometest/gcc_test#./test_weak
__lib_print : I want to testweak&&alias
application print_b : I want to testweak&&alias
分析:
从执行结果来看,print_a执行的是weak_symbol.c中的__lib_print的实现。print_b执行的是strong_symbol.c中的print_b实现。这个执行结果,我们是应该猜到的,需要说明一点是alias属性可以为一个函数提供很多不同的别名。这样,当我们提供api库的时候,如果多个api有相同的default实现,就可以通过alias机制提供一个default 实现。
gcc attribute weak & alias应用