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

被折叠的 条评论
为什么被折叠?



