该方法使用ctypes模块中的memmove函数将结构体数据对应的内存移动到缓冲区对应的位置,完成打包过程,相比上种方法较为麻烦。
代码如下:
1 # -*- coding: utf-8 -*-# 2 3 #------------------------------------------------------------------------------- 4 # Name: 以结构体形式直接打包参数包 5 # Description: 整个包大小为64Byte,包头为0X”FAA5 FBB5 FCC4 FDD5”,包尾为0X”5FA5 5FB5 5FC5 5FD5 ”,中间不足部分补0 6 # 发送的参数定义(有符号整型数字) 7 # cmdType = 1 # 1 Byte 8 # sigType = 2 # 1 Byte 9 # startFreq = 40 # 4 Byte 10 # stopFreq = 400 # 4 Byte 11 # deltFreq = 10 # 4 Byte 12 # pulseNum = 37 # 2 Byte 13 # pulseWidth = 0 # 4 Byte 14 # PRF = 25000000 # 4 Byte 15 # receiverFreq = 1000 # 4 Byte 16 # Author: lgk 17 # Date: 2018/6/14 18 #------------------------------------------------------------------------------- 19 20 import struct 21 import ctypes 22 import binascii 23 import re 24 25 #字节顺序定义 26 byteOrders = {'Native order':'@', 27 'Native standard':'=', 28 'Little-endian':'<', 29 'Big-endian':'>', 30 'Network order':'!'} 31 32 byteOrder = 'Little-endian' 33 34 fmt_head = fmt_tail = struct.Struct(byteOrders[byteOrder] + "8B") 35 fmt_body = struct.Struct(byteOrders[byteOrder] + "2b3i1h3i") 36 bufferLength = 64 37 38 def getSendInfo(info): 39 p = re.compile('.{1,2}') #匹配任意字符1-2次 40 t = ' '.join(p.findall(info.upper())) 41 return t 42 43 #定义本地形式结构体 44 class CMDParaNative(ctypes.Structure): 45 _pack_ = 1 46 _fields_ = [ 47 ('cmdType', ctypes.c_int8), 48 ('sigType', ctypes.c_int8), 49 ('startFreq', ctypes.c_int32), 50 ('stopFreq', ctypes.c_int32), 51 ('deltFreq', ctypes.c_int32), 52 ('pulseNum', ctypes.c_int16), 53 ('pulseWidth', ctypes.c_int32), 54 ('PRF', ctypes.c_int32), 55 ('receiverFreq', ctypes.c_int32) 56 ] 57 58 #定义大端形式结构体 59 class CMDParaBigEndian(ctypes.BigEndianStructure): 60 _pack_ = 1 61 _fields_ = [ 62 ('cmdType', ctypes.c_int8), 63 ('sigType', ctypes.c_int8), 64 ('startFreq', ctypes.c_int32), 65 ('stopFreq', ctypes.c_int32), 66 ('deltFreq', ctypes.c_int32), 67 ('pulseNum', ctypes.c_int16), 68 ('pulseWidth', ctypes.c_int32), 69 ('PRF', ctypes.c_int32), 70 ('receiverFreq', ctypes.c_int32) 71 ] 72 73 #定义小端形式结构体 74 class CMDParaLittleEndian(ctypes.LittleEndianStructure): 75 _pack_ = 1 76 _fields_ = [ 77 ('cmdType', ctypes.c_int8), 78 ('sigType', ctypes.c_int8), 79 ('startFreq', ctypes.c_int32), 80 ('stopFreq', ctypes.c_int32), 81 ('deltFreq', ctypes.c_int32), 82 ('pulseNum', ctypes.c_int16), 83 ('pulseWidth', ctypes.c_int32), 84 ('PRF', ctypes.c_int32), 85 ('receiverFreq', ctypes.c_int32) 86 ] 87 88 if byteOrder == 'Little-endian': 89 para = CMDParaLittleEndian(1, 2, 40, 400, 10, 37, 0, 25000000, 1000) 90 elif byteOrder == 'Big-endian': 91 para = CMDParaBigEndian(1, 2, 40, 400, 10, 37, 0, 25000000, 1000) 92 else: 93 para = CMDParaNative(1, 2, 40, 400, 10, 37, 0, 25000000, 1000) 94 95 headInfo = [0xFA, 0xA5, 0xFB, 0xB5, 0xFC, 0xC5, 0xFD, 0xD5] 96 tailInfo = [0x5F, 0xA5, 0x5F, 0xB5, 0x5F, 0xC5, 0x5F, 0xD5] 97 98 sendBuffer = ctypes.create_string_buffer(bufferLength) #创建发送缓冲区 99 100 #将待发送的参数打包到缓冲区 101 fmt_head.pack_into(sendBuffer, 0, *headInfo) 102 fmt_tail.pack_into(sendBuffer, bufferLength-fmt_tail.size, *tailInfo) 103 #将结构体数据对应的内存移动到缓冲区对应的位置 104 ctypes.memmove(ctypes.addressof(sendBuffer)+fmt_head.size, ctypes.byref(para), ctypes.sizeof(para)) 105 # ctypes.memmove(ctypes.byref(sendBuffer, fmt_head.size), ctypes.byref(para), ctypes.sizeof(para)) #与上面一行等价 106 107 #打印出字节流的16进制信息(byteOrder = 'Little-endian') 108 #FA A5 FB B5 FC C5 FD D5 01 02 28 00 00 00 90 01 00 00 0A 00 00 00 25 00 00 00 00 00 40 78 7D 01 E8 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5F A5 5F B5 5F C5 5F D5 109 print(getSendInfo(binascii.hexlify(sendBuffer)))