函式指標成員是可變參函式:函式指標數組裡的成員是引數各不相同的函式
api_public.h
/定義函式指標陣列的下標號*/
enum {
API_RSVD =0,
API_GETC,
API_PUTC,
API_TSTC,
API_PUTS,
API_RESET,
API_GET_SYS_INFO,
API_UDELAY,
API_GET_TIMER,
API_DEV_ENUM,
API_DEV_OPEN,
API_DEV_CLOSE,
API_DEV_READ,
API_DEV_WRITE,
API_ENV_ENUM,
API_ENV_GET,
API_ENV_SET,
API_MAXCALL
};
Api.c
#include <api_public.h>
typedef int(*cfp_t)(va_list argp);
/*指標數組裡某一個函式的定義*/
static int API_dev_read(va_list ap)
{
structdevice_info *di;
void *buf;
lbasize_t*len_stor, *act_len_stor;
lbastart_t*start;
int*len_net, *act_len_net;
/* 1. argis ptr to the device_info struct */
di =(struct device_info *)va_arg(ap,u_int32_t);/*指標大小都是4位元組大小,所以可以用32位資料大小來接收可變引數struct device_info *di*/
if (di ==NULL)
returnAPI_EINVAL;
/* XXXshould we check if device is open? i.e. the ->state ? */
if(di->cookie == NULL)
returnAPI_ENODEV;
/* 2. argis ptr to buffer from where to put the read data */
buf =(void *)va_arg(ap,u_int32_t);//接收可變引數void *buf
if (buf ==NULL)
returnAPI_EINVAL;
if(di->type & DEV_TYP_STOR) {
/*3. arg - ptr to var with # of blocks to read */
len_stor= (lbasize_t *)va_arg(ap,u_int32_t);
if(!len_stor)
returnAPI_EINVAL;
if(*len_stor <= 0)
returnAPI_EINVAL;
/*4. arg - ptr to var with start block */
start= (lbastart_t *)va_arg(ap,u_int32_t);
/*5. arg - ptr to var where to put the len actually read */
act_len_stor= (lbasize_t *)va_arg(ap, u_int32_t);
if(!act_len_stor)
returnAPI_EINVAL;
*act_len_stor= dev_read_stor(di->cookie, buf, *len_stor, *start);
} else if(di->type & DEV_TYP_NET) {
/*3. arg points to the var with length of packet to read */
len_net= (int *)va_arg(ap,u_int32_t);
if(!len_net)
returnAPI_EINVAL;
if(*len_net <= 0)
returnAPI_EINVAL;
/*4. - ptr to var where to put the len actually read */
act_len_net= (int *)va_arg(ap,u_int32_t);
if(!act_len_net)
returnAPI_EINVAL;
*act_len_net= dev_read_net(di->cookie, buf, *len_net);
} else
returnAPI_ENODEV;
return 0;
}
static cfp_t calls_table[API_MAXCALL] = {NULL, };//只初始化第一個成員
/*初始化陣列*/
void api_init(void)
{
structapi_signature *sig = NULL;
/* TODOput this into linker set one day... */
calls_table[API_RSVD]= NULL;
calls_table[API_GETC]= &API_getc;
calls_table[API_PUTC]= &API_putc;
calls_table[API_TSTC]= &API_tstc;
calls_table[API_PUTS]= &API_puts;
calls_table[API_RESET]= &API_reset;
calls_table[API_GET_SYS_INFO]= &API_get_sys_info;
calls_table[API_UDELAY]= &API_udelay;
calls_table[API_GET_TIMER]= &API_get_timer;
calls_table[API_DEV_ENUM]= &API_dev_enum;
calls_table[API_DEV_OPEN]= &API_dev_open;
calls_table[API_DEV_CLOSE]= &API_dev_close;
calls_table[API_DEV_READ] = &API_dev_read;
calls_table[API_DEV_WRITE]= &API_dev_write;
calls_table[API_ENV_GET]= &API_env_get;
calls_table[API_ENV_SET]= &API_env_set;
calls_table[API_ENV_ENUM]= &API_env_enum;
calls_no =API_MAXCALL;
/*可變參函式*/
int syscall(intcall, int *retval, ...)
{
va_list ap;
int rv;
if (call< 0 || call >= calls_no) {
debugf("invalidcall #%d\n", call);
return0;
}
if(calls_table[call] == NULL) {
debugf("syscall#%d does not have a handler\n", call);
return0;
}
va_start(ap, retval); //通過va_start從retval中讀取引數
rv =calls_table[call](ap);//呼叫指標數組裡的函式
if (retval!= NULL)//使用者如果不想返回資料就帶入引數指標為NULL
*retval= rv;
return 1;
}
/*呼叫可變參函式*/
int ub_dev_read(inthandle, void *buf, lbasize_t len, lbastart_t start, lbasize_t *rlen)
{
structdevice_info *di;
lbasize_tact_len;
int err =0;
if(!dev_stor_valid(handle))
returnAPI_ENODEV;
di =&devices[handle];
if(!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len))
returnAPI_ESYSC;
if (!err&& rlen)
*rlen= act_len;
returnerr;
}
函式指標數組裡的成員是引數各不相同的函式,即成員是可變參函式。