需求
使用C语言发送任意个通道的波形数据,要求:接口固定,但参数个数不固定,DSP的开发环境只能用C语言
实现
stdarg
是C语言标准库的一部分,我们通过它来实现类似C++的函数模板
比如给上位机发送数据,一个通道为一个float,可变参数num
代表可以发n个通道的波形数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| void SCIA_sendFrame_JustFloat(int num, ...) { while(isTransmitting) { }
txBufferIndex = 0; txDataCount = 0;
va_list args; va_start(args, num);
int i; for(i = 0; i < num; i++) { float value = (float)va_arg(args, double); FloatUnion data; data.DataFloat = value; txBuffer[txDataCount++] = (uint8_t)(data.DataUint16[0] & 0xFF); txBuffer[txDataCount++] = (uint8_t)((data.DataUint16[0] >> 8) & 0xFF); txBuffer[txDataCount++] = (uint8_t)(data.DataUint16[1] & 0xFF); txBuffer[txDataCount++] = (uint8_t)((data.DataUint16[1] >> 8) & 0xFF); } va_end(args);
txBuffer[txDataCount++] = 0x00; txBuffer[txDataCount++] = 0x00; txBuffer[txDataCount++] = 0x80; txBuffer[txDataCount++] = 0x7F;
isTransmitting = true; txBufferIndex = 0; SCI_enableInterrupt(SCIA_BASE, SCI_INT_TXFF); }
|
定义可变参数,获取可变参数个数(这个是在运行时阶段获取的,跟C++的模板函数不一样)
1 2 3 4 5 6
| va_list args; va_start(args, num);
......
va_end(args);
|
参数的访问和使用:从0-num
遍历可变参数列表,float在可变参数中提升为double,遍历动作要在va_start
和va_end
之内,va_arg
是一个出栈动作,并不是基于索引的
1 2 3 4 5 6 7 8 9 10
| for(i = 0; i < num; i++) { float value = (float)va_arg(args, double); FloatUnion data; data.DataFloat = value; txBuffer[txDataCount++] = (uint8_t)(data.DataUint16[0] & 0xFF); txBuffer[txDataCount++] = (uint8_t)((data.DataUint16[0] >> 8) & 0xFF); txBuffer[txDataCount++] = (uint8_t)(data.DataUint16[1] & 0xFF); txBuffer[txDataCount++] = (uint8_t)((data.DataUint16[1] >> 8) & 0xFF); }
|
总结
- 可变参数列表是一个数据栈,C语言函数运行调用时,参数
从右到左
压栈,取参数是从左到右
出栈,跟函数参数调用的顺序保持一致
- C++的函数模板是编译时确定的,通常会生成多份函数实例