函数指针成员是可变参函数:函数指针数组里的成员是参数各不相同的函数

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;

}

函数指针数组里的成员是参数各不相同的函数,即成员是可变参函数。

 

 

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值