strongswan中使用METHOD来定义函数(方法),如下get_first函数定义。
METHOD(linked_list_t, get_first, status_t,
private_linked_list_t *this, void **item)
{
if (this->count == 0)
return NOT_FOUND;
*item = this->first->value;
return SUCCESS;
}
METHOD宏定义如下:
#define METHOD(iface, name, ret, this, ...) \
static ret name(union {iface *_public; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
static typeof(name) *_##name = (typeof(name)*)name; \
static ret name(this, ##__VA_ARGS__)
METHOD宏各个参数的说明以及对应于的get_first函数的各个参数如下。
iface - 公共结构 - linked_list_t
name - 函数(方法)名称 - get_first
ret - 函数返回值类型 - status_t
this - 私有结构 - private_linked_list_t *this
... - 可变参数 - void **item
METHOD宏重新布局如下。其由三部分组成,第一部分为函数声明,首个参数为transparent_union属性修饰的联合体,联合体内容为对应结构(如linked_list_t)的公共和私有结构体;
#define METHOD(iface, name, ret, this, ...) \
static ret name(union { \
iface *_public; \
this; \
} __attribute__((transparent_union)), \
\
##__VA_ARGS__); \
\
static typeof(name) *_##name = (typeof(name)*)name; \
\
static ret name(this, ##__VA_ARGS__)
METHOD定义的函数为静态,文件内部使用时首个参数为私有结构体,如private_linked_list_t。外部通过公共函数访问时,传入的参数为公共结构体,如linked_list_t。使用transparent_union防止编译器报错。
第二部分为函数重定义,在函数名前增加一个下划线;例如get_first与_get_first定义为同一个函数。程序编译时,GCC将优化掉带前缀下划线的定义函数。第三部分为函数定义,之后紧跟函数体。
如下为METHOD宏展开之后的get_first函数定义。
static status_t get_first(union {
linked_list_t *_public;
private_linked_list_t *this;
} __attribute__((transparent_union)),
void **item);
static typeof(get_first) *_get_first = (typeof(get_first)*)get_first;
static status_t get_first(private_linked_list_t *this, void **item)
{
if (this->count == 0)
return NOT_FOUND;
*item = this->first->value;
return SUCCESS;
}
METHOD2宏
如下get_source函数使用METHOD2宏定义。
METHOD2(esp_packet_t, packet_t, get_source, host_t*,
private_esp_packet_t *this)
{
return this->packet->get_source(this->packet);
}
类似于METHOD宏定义,差别在于METHOD2在函数的首个联合体参数中增加了一个公共结构iface2。
/* Same as METHOD(), but is defined for two public interfaces.
*/
#define METHOD2(iface1, iface2, name, ret, this, ...) \
static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
static typeof(name) *_##name = (typeof(name)*)name; \
static ret name(this, ##__VA_ARGS__)
如下第一个参数联合体,包括两个公共接口结构iface1和iface2,对应于get_source函数的esp_packet_t和packet_t两个参数;以及第三个参数this对应于private_esp_packet_t *this。
union {
iface1 *_public1;
iface2 *_public2;
this;
} __attribute__((transparent_union))
transparent_union属性
transparent_union属性用于修饰联合体定义,使用此联合体作为参数的函数,再被调用的时候被特殊对待。首先,调用者可以使用联合体中的任何一个成员类型作为函数参数,不需要进行强制类型转换。此外,如果联合体中包含(非void)指针类型,则相应的参数也可以是常量NULL指针或void类型指针;如果联合体中包含void指针类型,则相应的参数可以是任何指针类型。如果联合体成员类型是指针,则必须遵守类型上的修饰符(比如const),就像正常的指针转换一样。
其次,传递给函数的透明联合体参数,使用的是透明联合体的第一个成员的调用规约而不是联合体本身的调用规约。联合体的所有成员必须拥有相同的机器表示;这对于传递的参数能正常工作是必须的。
具体参见https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Type-Attributes.html。