变参函数相关介绍和封装

本文介绍如何实现可变参数函数的二次封装,以解决在visa接口如viPrintf、viScanf等中,由于每条通信涉及多条指令导致的log记录复杂性。通过封装通信接口,将log打印和异常处理集成,简化代码逻辑。关键点在于利用C语言的可变参数宏来实现这一功能。

实现可变参数函数的二次封装,如printf、viPrintf等

问题描述:visa接口viPrintf、viScanf、viQueryf等具有可变参数的封装,每条通信会发送多读取指令,现需要对发送与接收的指令进行log记录,但指令数量多,逐条提取打印会引入过多的无关代码逻辑

解决方法:封装通信接口,将所有需要的操作封装进接口,如:将log打印、异常处理等封装到中间接口中,编码时只需要使用新封装的接口即可实现log打印与异常处理功能;

下面介绍涉及到的关键变量与函数,主要是利用c语言可变参数宏实现,相关函数及类型介绍见下表(代码索引对应代码中的实现)

函数及类型作用代码索引
va_list参数列表指针1
va_start(va_list va, const char* fmt)初始化参数列表指针va,使其指向格式化字符串fmt的首位2
unsigned long _vscprintf(const char* fmt, va_list va)返回格式化参数最终表示的字符串长度,fmt为原始格式化字符串;3
vsprintf_s(char* des, length, char* fmt, va_list va)格式化字符串,利用va_list,完成 fmt 的格式化工作4
type* va_arg(va_list va, type)将va解释为type型变量,并返回其地址,将返回地址传递给读取函数,如scanf,可获得输入数据5、6
代码实现:
int CVisa::cViPrintf(ViSession vi, ViConstString writeFmt, ...)
{

    int status = 0;
    va_list arg;                          // 1 参数列表指针
    va_start(arg, writeFmt);              // 2 初始化va_list, arg当前指向fmt的首位

    unsigned int length = _vscprintf(writeFmt, arg) + 1;  // 3
    char* buff = new char[length];
    memset(buff,'\0',length);
    vsprintf_s(buff, length,(char*)writeFmt, arg);   // 4 格式化到buf中

    status = viPrintf(vi, buff);          // 封装原始函数,使其具有打印log功能
    va_end(arg);

    char* writeLog = atoNoEnter((char*&)buff);  // 打印log时剔除\n
    char outSymbol[3] = ">>";
    VisaLogger::getInstance()->write(outSymbol, writeLog);  // 输出记录
    delete buff;
    buff = nullptr;
    return status;
}
ViStatus CVisa::cViQueryf(ViSession vi, ViConstString writeFmt, ViConstString readFmt, ...)
{
    ViStatus status = 0;
    va_list arg;                          // 参数列表指针
    va_start(arg, readFmt);               // 初始化va_list, arg当前指向fmt的首位
    char* ptr = va_arg(arg, char*);       // 5 指定arg类型,并使ptr指向该地址,以便返回结果
    status = viQueryf(vi, writeFmt, readFmt, ptr);  // 6
    va_end(arg);

    char * writeLog = atoNoEnter((char*&)writeFmt);
    char outSymbol[3] = ">>";
    char inSymbol[3] = "<<";
    VisaLogger::getInstance()->write(outSymbol, writeLog);    // 输出记录
    if(0==status)
        VisaLogger::getInstance()->write(inSymbol, ptr);      // 回执记录
    else
    {
        char errMsg[64] = "error code: \0";
        char errCode[16] = {0};
        itoa(status, errCode, 16);
        strcat(errMsg, errCode);
        VisaLogger::getInstance()->write(inSymbol, errMsg);              // 回执记录
    }
    return status;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值