strongswan中函数的定义使用了一个叫METHOD的宏,此宏的定义在object.h头文件中给出。
此宏包括3部分。
第一部分是对名为name的函数进行声明。即:
static ret name(union {iface *_public; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__);这里用到了两个关键字,__attribute__和transparent_union。
__attribute__是GCC对C11语法的扩展。使用__attribute__可以指定函数、对象和类型的属性。在《C语言编程魔法书:基于C11标准》中有详细的介绍。
transparent_union是一个属性,该属性附加到联合类型定义之后,指示具有该联合类型的任何函数参数都会以特殊方式处理对该函数的调用。
首先,对应于透明联合类型的参数可以是union中的任何类型; 不需要类型转换。 另外,如果union包含指针类型,则相应的参数可以是空指针常量或void指针表达式; 如果union包含void指针类型,则相应的参数可以是任何指针表达式。 如果union成员类型是指针,则必须遵守引用类型上的const之类的限定符,就像使用正常的指针转换一样。
其次,参数使用透明联合的第一个成员的调用约定传递给函数,而不是联合本身的调用约定。 联合体的所有成员必须具有相同的机器表示; 这对于所传参数的正确运行是必要的。
transparent_union的使用示例可参考:http://toves.freeshell.org/xueg/
回到第一部分的代码,__attribute__((transparent_union))修饰的是union {iface *_public; this;} ,说明在引用参数的时候可以不用区分参数是iface类型还是this所表示的类型。实际上,通常this类型的第一个参数的类型是与_public的类型相同的。如下图:
上图中的iface即stroke_socket_t,destroy即_public,destroy的类型为stroke_socket_t*,this的类型为private_stroke_socket_t*,而private_stroke_socket_t的第一个参数即为stroke_socket_t,如下图:
由此可见数据结构设计的巧妙之处。
第二部分是将名为name的函数赋给了函数指针_name。即:
static typeof(name) *_##name = (typeof(name)*)name;
这里用到的关键字typeof也是GCC对C11标准的扩展。通过typeof,我们可以在编译时获取到指定对象的类型,并且typeof表达式可作为类型用于声明其他对象。
_name也指明了在对象创建并初始化时,public方法的赋值总是带有下划线的原因。
第三部分是对name函数的真正定义处。即
static ret name(this, ##__VA_ARGS__)
{
}
花括弧中的定义在对应的.c源文件中。