函数封装技巧---函数指针+void*变量

前言

所有技术的学习,第一步都是先整理招式,等招式熟练了,再学习内功。最后融会贯通。这次整理一下公司代码中函数指针的用法。

第一步:定义一个回调函数

注意到:
1、输入参数是void *型,这样好处是今后如果只想传入一个参数,那直接char *强转即可,如果涉及到多个参数,可以定一个结构进去,真正做到函数通用
2、输出参数是void **好处自然不用说,输出的内容完全自己定义
3、下面的函数指针通用性很强

typedef int (*hikos_callback) (
    enum storage_action_e action_e, const long id, void *inbuffer, void **outbuffer);

第二步:公共函数调用回调函数

1、定义一个公共函数来调用上述函数指针,可以让多个小组协同开发
2、公共函数的后续参数,都是函数指针的参数

ret = hikos_storage(hikos_ceph, global_action, global_command, global_inbuffer, (void *)&outbuffer);

公共函数 函数实现

int hikos_storage(hikos_callback callback_f, 
    enum storage_action_e action_e, const long id, void *inbuffer, void **outbuffer)
{
    int ret = 0;
    int fd = -1;
    int file_seek = 0;
    cs_file_t *p_cs_file = NULL;

    int action_value = 0;
    long command_value = 0;
    char command_str[64] = {0};

    p_cs_file = malloc(sizeof(cs_file_t));
    if (!p_cs_file)
    {
        common_print(PRINT_ALERT, "malloc error");
        ret = ERROR_MALLOC;
        goto out;
    }
    memset(p_cs_file, 0, sizeof(cs_file_t));

    fd = open(STORAGE_CS_PATH, O_RDONLY);
    if (-1 == fd)
    {
        common_print(PRINT_ALERT, "%s: open error", STORAGE_CS_PATH);
        ret = ERROR_PATH;
        goto out;
    }

    flock(fd, LOCK_EX);

    while (sizeof(cs_file_t) == pread(fd, p_cs_file, sizeof(cs_file_t), file_seek)) 
    {
        if (!strcmp(p_cs_file->api_action, "get")) 
        {
            action_value = STORAGE_ACTION_GET;
        } 
        else if (!strcmp(p_cs_file->api_action, "add")) 
        {
            action_value = STORAGE_ACTION_ADD;
        } 
        else if (!strcmp(p_cs_file->api_action, "set")) 
        {
            action_value = STORAGE_ACTION_SET;
        } 
        else if (!strcmp(p_cs_file->api_action, "del")) 
        {
            action_value = STORAGE_ACTION_DEL;
        } 
        else if (!strcmp(p_cs_file->api_action, "chk")) 
        {
            action_value = STORAGE_ACTION_CHK;
        }

        sscanf(p_cs_file->api_command, "%lx:%s", &command_value, command_str);
        
        if (action_e == action_value && id == command_value) 
        {
            if (1 == p_cs_file->api_enable)
            {
                flock(fd, LOCK_UN);

                ret = callback_f(action_e, id, inbuffer, (void *)outbuffer);

                goto out;
            }
            else
            {
                ret = ERROR_DISABLE;
            }
            
            break;
        }
        
        file_seek += sizeof(cs_file_t);
        memset(p_cs_file, 0, sizeof(cs_file_t));
    }

    flock(fd, LOCK_UN);
    
    out:
        if (-1 != fd)
        {
            close(fd);
            fd = -1;
        }

        if (p_cs_file)
        {
            free(p_cs_file);
            p_cs_file = NULL;
        }
        
        return ret;        
}

第三步:举例其中一个小组子模块

1、使用枚举来控制功能分类

int hikos_ceph(
    enum storage_action_e action_e, const long id, void *inbuffer, void **outbuffer)
{
    int ret = -1;

    switch (action_e)
    {
        case STORAGE_ACTION_GET:       
            ret = ceph_get(id, inbuffer, outbuffer);
            break;
        case STORAGE_ACTION_ADD:
            ret = ceph_add(id, inbuffer, outbuffer);
            break;
        case STORAGE_ACTION_SET:
            ret = ceph_set(id, inbuffer, outbuffer);
            break;
        case STORAGE_ACTION_DEL:
            ret = ceph_del(id, inbuffer, outbuffer);
            break;
        case STORAGE_ACTION_CHK:
            ret = ceph_chk(id, inbuffer, outbuffer);
            break;
        default:
            goto out;
    }
    
    return ret;

    out:
        return ret;
}

第四步:再用id控制小组各个成员开发

static int  ceph_add(const long id, void *inbuffer, void **outbuffer)
{
    int ret = -1;

    switch (id)
    {
        case 0x00112000:
            break;

        case CEPH_CLUSTER_ADD_NODE:	
            ret = ceph_add_node(inbuffer, outbuffer);
            break;

        case CEPH_POOL_CREATE: 
            ret = ceph_pool_create(inbuffer,NULL);
            break;
            
        case CEPH_POOL_EXPAND:
            ret = ceph_pool_expand(inbuffer,NULL);
            break; 
            
        default:
            ret = ERROR_UNKNOW;
            goto out;
    }
    return ret;

    out:
        return ret;
}
/* ceph 模块命令 */
typedef enum 
{
    CEPH_RPM_INSTALL = 0x00130000,           /*安装ceph rpm 包*/
    CEPH_RPM_STATUS,                                 /*ceph安装包状态*/
    CEPH_CLUSTER_CREATE,                          /*ceph集群创建*/
    CEPH_CLUSTER_ADD_NODE,                      /*ceph集群扩容*/
    CEPH_CLUSTER_CREATE_PRO,
    CEPH_CLUSTER_ADD_NODE_PRO,
    CEPH_PURE_DEPLOY_PROGRESS,
    CEPH_CLUSTER_ERROR = 0x00130FFF,

    CEPH_DISK_GET_DISK_LIST = 0x00131000,    /*获取ceph可用磁盘列表*/
    CEPH_DISK_DEL_POOL_DISK,			     /*删除存储池的磁盘*/
    CEPH_DISK_GET_OSD_INFO,		            /*获取osd状态信息*/
    CEPH_DISK_ERROR = 0x00131FFF,	            /* 未知命令码*/ 

    CEPH_POOL_CREATE = 0x00132001,              /*ceph存储池创建*/
    CEPH_POOL_EXPAND,                                   /* ceph存储池扩容*/
    CEPH_POOL_LIST,                                         /*ceph存储池列表*/
    CEPH_POOL_DETAIL,                                     /*ceph存储池详情*/
    CEPH_POOL_DELETE,                                    /*ceph删除存储池*/
    CEPH_POOL_PERFORMANCE,                          /*pool性能采集*/ 
    CEPH_POOL_PROGRESS,                             /*进度信息*/
    CEPH_POOL_ERROR = 0x00132FFF,

    CEPH_ALARM_CLUSTER = 0x00133001,        /* ceph集群告警 */
    CEPH_ALARM_CAPACITY,                            /* ceph容量告警 */
    CEPH_ALARM_ERROR = 0x00133FFF    
}CEPH_COMMAND_E;

版权声明:本文为qq_23929673原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。