mingdu.zheng <at> gmail <dot> com
http://blog.youkuaiyun.com/zoomdy/article/details/8884825
1. externC
eCos中使用C++源文件组织的需要给C代码调用的函数均添加了externC或__externC。 例如:(kernel/../src/intr/intr.cxx:333
)
externC void interrupt_end( cyg_uint32 isr_ret, Cyg_Interrupt *intr, HAL_SavedRegisters *regs ) { ... }
externC 宏在infra/.../include/cyg_type.h:65
中定义
#ifdef __cplusplus # define __externC extern "C" #else # define __externC extern #endif #define externC __externC
在C++代码中 externC或__externC被定义成 extern “C”,在C代码中被定义成空白。 C++因为支持函数重载,允许相同的函数名被重复定义,只要函数的入参不同。 但是底层工具,例如链接器,是不支持函数重载的,每个函数必须有唯一的标识符, 因此C++在编译的过程中会有个名称转换的过程,在函数名的前后加上其它信息,例如入参类型等。
int add(int a, int b) { return a + b; } char add(char a, char b) { return a + b; }
将这两个add函数放到C++源文件中进行编译(这里使用arm-eabi-gcc,不同的编译器,名称转换规则不相同), 然后反汇编生成的目标文件,可以发现没有标识符为add的符号, 只有_Z3addii和_Z3addcc这两个符号。 extern “C”的作用是告诉编译器该函数以C语言的规则处理,也就是说,该函数不进行名称转换。 对上述代码稍作修改。
int add(int a, int b) { return a + b; } extern "C" char add(char a, char b) { return a + b; }
重新编译并反汇编,两个符号分别为_Z3addii和add。添加 extern “C” 的函数名没有被转换。 只有未进行名称转换的函数才能被C代码正确调用。
eCos内核API函数的声明和定义均会在函数原型的后面加上__THROW宏,例如:(kernel/.../include/kapi.h:136
)
void cyg_scheduler_unlock(void) __THROW;
__THROW宏在infra/.../include/cyg_type.h
中定义
#ifdef __cplusplus # define __THROW throw() #else # define __THROW #endif
如果是C++代码,那么__THROW被定义为throw(),如果是C代码,那么__THROW定义为空白。 C++支持异常特性,可以在C++代码中throw出异常,但是eCos作为嵌入式系统并不支持异常处理特性。 在函数名后添加throw()告诉编译器该函数不会抛出异常并指示编译器按照没有异常情况的方式优化代码。
函数声明或定义使用throw的用法:
void fun() throw(); // 表示不会抛出任何类型异常 void fun() throw(int); // 表示只抛出int类型异常 void fun() throw(int, char); // 表示抛出int,char类型异常 void fun() throw(...); // 表示抛出任何类型异常 void func(); // 默认情况表示抛出任何类型异常