近日在看apache的源码,在他的module的定义中,ap_hook_handler是一个非常重要的函数。用来在apache中注册你的自定义module中的callback函数。
遍搜ap_hook_handler,寻不得在哪定义的。最后发现,这家伙把所有的hook函数都定义在宏里。比代码混淆都NB。作为一个长期从事.net开发的人而言,可称得上变态了。
A:
AP_DECLARE_HOOK(int,handler,(request_rec *r))
B:
#define AP_DECLARE_HOOK(ret,name,args) APR_DECLARE_EXTERNAL_HOOK(ap,AP,ret,name,args)
C:
#define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
D:
typedef ret ns##_HOOK_##name##_t args; \
link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \
const char * const *aszPre, \
const char * const *aszSucc, int nOrder); \
link##_DECLARE(ret) ns##_run_##name args; \
APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); \
typedef struct ns##_LINK_##name##_t \
{ \
ns##_HOOK_##name##_t *pFunc; \
const char *szName; \
const char * const *aszPredecessors; \
const char * const *aszSuccessors; \
int nOrder; \
} ns##_LINK_##name##_t;
E:
#define AP_DECLARE(type) type
F:
#define APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \
link##_DECLARE(apr_array_header_t *) ns##_hook_get_##name(void)
把A套入B,得到:
ns = ap
name = handler
arg = (request_rec *r)
把B套入C,又得到:
link = AP
把C套入D,再加上E中的声明, 最终得到:
typedef int ap_HOOK_handler_t (request_rec *r);
void ap_hook_handler(ap_HOOK_handler_t *pf, char * const *aszPre, char * const *aszSucc, int nOrder);
int ap_run_handler (request_rec *r);
APR_IMPLEMENT_HOOK_GET_PROTO(ap,AP,handler);
typedef struct ap_LINK_handler_t
{
ap_HOOK_handler_t *pFunc;
const char *szName;
const char * const *aszPredecessors;
const char * const *aszSuccessors;
int nOrder;
} ap_LINK_handler_t;
其实到这里,我已经看到了ap_hook_handler的声明。因此才得以合法的调用ap_hook_handler。一切来源于代码A,A中的一行,最终会被替代成一堆struct定义和函数声明。让我们继续挖一下,把他完全展开,将F也套入APR_IMPLEMENT_HOOK_GET_PROTO(ap,AP,handler);,得到:
typedef int ap_HOOK_handler_t (request_rec *r);
void ap_hook_handler(ap_HOOK_handler_t *pf, char * const *aszPre, char * const *aszSucc, int nOrder);
int ap_run_handler (request_rec *r);
apr_array_header_t * ap_hook_get_handler(void);
typedef struct ap_LINK_handler_t
{
ap_HOOK_handler_t *pFunc;
const char *szName;
const char * const *aszPredecessors;
const char * const *aszSuccessors;
int nOrder;
} ap_LINK_handler_t;
感谢netbeans,在Linux下,着实除了他,别的工具真的很难挖出这个大萝卜。