AP_DECLARE(int) ap_run_status_hook(request_rec* r,int flags)
{
ap_LINK_status_hook_t *pHook;
int n;
int rv;
apr_array_header_t *pHookArray=apr_optional_hook_get(status_name);
if(!pHookArray)
return ok;
pHook=(ap_LINK_status_hook_t *)pHookArray->elts;
for(n=0 ; n < pHookArray->nelts ; ++n)
{
rv=(pHook[n].pFunc)(r,flags);
if(rv != ok && rv != decline)
return rv;
}
return ok;
}
5.5.8 可选函数
与挂钩存在类似的问题,函数也可能存在可选挂钩的问题。如果Apache在调用某一个函数的时候,该函数尚未被加载,会发生什么呢。你可能觉得DSO是个好的解决方法。如果指定的函数没有,则动态加载DSO模块进行查找。不过这种策略并不但是最完美的方案。首先,不是所有的平台都支持DSO;另一方面,
可选函数的特点正如其名,这就决定了它相对于Apache的动态性。正常的函数都是编写之后才会加入Apache中进行编译,而且一旦编译就无法更改。而可选函数则是在需要的时候动态产生的。在产生之前,没有人为之进行过专门的编写,因此链接代码中自然也就找不到该函数的实现。
可选函数的使用可以分为五大步骤:声明、实现、注册、获取以及函数调用。
5.5.8.1.可选函数的声明
声明一个可选函数通过宏APR_DECLARE_OPTIONAL_FN来实现,比如我们如果想声明一个optional_fun可选函数,其返回int类型,参数需要字符串类型,那么声明可以如下:
APR_DECLARE_OPTIONAL_FN(int,optional_fun,(const char* params))
APR_DECLARE_OPTIONAL_FN宏定义如下:
#define APR_DECLARE_OPTIONAL_FN(ret,name,args) \
typedef ret (APR_OPTIONAL_FN_TYPE(name)) args
如果将上面的宏展开,则可以看出,该宏只是声明了一个apr_OFN_optional_fun_t类型的函数指针:
typedef int (apr_OFN_optional_fun_t)(const char* params)
一旦声明完毕,我们则将其进行实现如下,在实现中必须注意名称以及函数参数类型的匹配:
int optional_fun(const char* params)
{
……
return 0;
}
5.5.8.2.可选函数的注册