我试图将此c代码翻译成python,但我遇到了char*
到ushort*
转换的问题:
void sendAsciiCommand(string command) {
unsigned int nchars = command.length() + 1; // Char count of command string
unsigned int nshorts = ceil(nchars / 2); // Number of shorts to store the string
std::vector<unsigned short> regs(nshorts); // Vector of short registers
// Transform char array to short array with endianness conversion
unsigned short *ascii_short_ptr = (unsigned short *)(command.c_str());
for (unsigned int i = 0; i < nshorts; i++)
regs[i] = htons(ascii_short_ptr[i]);
return std::string((char *)regs.data());
}
我在Python 2.7中尝试使用此代码的时间很长:
from math import ceil
from array import array
command = "hello"
nchars = len(command) + 1
nshorts = ceil(nchars/2)
regs = array("H", command)
但它给了我错误:
ValueError:字符串长度不是项目大小的倍数
任何帮助?
答案 0 :(得分:0)
例外文字:
ValueError: string length not a multiple of item size
表示所说的内容,即您尝试创建数组的字符串长度必须是项目大小的倍数。在这种情况下,项目大小是unsigned short
的大小,即2个字节。因此,字符串的长度必须是2的倍数。hello
的长度为5,它不是2的倍数,因此您无法从中创建一个包含2个字节整数的数组。如果字符串长度为6个字节,它将起作用,例如hello!
。
>>> array("H", 'hello!')
array('H', [25960, 27756, 8559])
您可能仍需要转换为网络字节顺序。 array
使用机器上的本机字节顺序,因此如果您的本机字节顺序是小端,则需要将其转换为big endian(网络字节顺序)。如果需要,使用sys.byteorder
检查并array.byteswap()
交换字节顺序:
import sys
from array import array
s = 'hello!'
regs = array('H', s)
print(regs)
# array('H', [25960, 27756, 8559])
if sys.byteorder != 'big':
regs.byteswap()
print(regs)
# array('H', [26725, 27756, 28449])
但是,如果需要,可以更轻松地使用struct.unpack()
直接转换为网络字节顺序:
import struct
s = 'hello!'
n = len(s)/struct.calcsize('H')
regs = struct.unpack('!{}H'.format(n), s)
print(regs)
#(26725, 27756, 28449)
如果你真的需要array
:
regs = array('H', struct.unpack('!{}H'.format(n), s))
还值得指出您的C ++代码包含错误。如果字符串长度为奇数,则将在字符串末尾读取额外字节,这将包含在转换后的数据中。该额外字节将为\0
,因为C字符串应为空终止,但应忽略最后一个unsigned short
,或者您应检查该字符串的长度是{{1}的倍数就像Python一样。