1. 程式人生 > >函式指標成員是可變參函式:函式指標數組裡的成員是引數各不相同的函式

函式指標成員是可變參函式:函式指標數組裡的成員是引數各不相同的函式

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_startretval中讀取引數

       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;

}

函式指標數組裡的成員是引數各不相同的函式,即成員是可變參函式。