2017-03-07 1 views
2

파이썬에서 바이트로 정의한대로 ctype.Structure에 액세스하려고합니다 (b'').ctypes를 바이트로 변환하는 방법

올바른 방법인지 모르겠습니까? 다른 장치에 헤더 (아키텍처가 없어야 함)를 보내야합니다.

class Header(ctypes.Structure): 
    _pack_ = 2 
    _fields_ = [ 
     ('version', c_uint8), 
     ('additional_options', c_uint8), 
     ('soft_version', c_uint16), 
     ('compilation_time', c_uint8 * 6), 
     ('crc', c_uint16) 
    ] 

가 지금은 CRC를 계산하기 위해 필요로

그래서 내가 예를 들어 그것을 정의했다. 마감일 : version에서 compilation_time까지 바이트로 작업하는 함수가 있습니다.

그래서 나를 위해 그것은 그냥 ctypes.Structure 바이트 (b ")로 변환하거나 직접 메모리에 액세스하고 마지막 두 바이트를 변경합니다.

struct을 사용해 보았지만 pragma 옵션을 찾지 못했습니다.

답변

2

struct 당신이 원하는 무엇인가 :

>>> import struct 
>>> fmt = struct.Struct('<BBH6s') 
>>> data = fmt.pack(1,2,3,b'170207') 
>>> data 
b'\x01\x02\x03\x00170207' 
>>> crc = <do your calculation> 
>>> data += struct.pack('<H',crc) 

< 수단 리틀 엔디안 팩 및 것 C와 같은 패딩 바이트를 추가하지 않습니다, 그래서 _pack_이 필요하지 않습니다. 빅 엔디안이 필요한 경우 대신 >을 사용하십시오.

나는 6s을 사용했으며 정확한 길이의 바이트 문자열을 전달했습니다. 원시 바이트를 전달하려면 6B을 사용하고 한 문자열 대신 6 바이트를 나열하십시오.

다음은 ctypes 솔루션입니다. crc32는 데모 목적으로 라이브러리에서 사용할 수 있으므로 crc32를 사용했습니다.

from ctypes import * 
from binascii import crc32 

class Header(Structure): 
    _pack_ = 2 
    _fields_ = [ 
     ('version', c_uint8), 
     ('additional_options', c_uint8), 
     ('soft_version', c_uint16), 
     ('compilation_time', c_uint8 * 6), 
     ('crc', c_uint32) 
    ] 

h = Header(1,2,3) 
h.compilation_time = (c_uint8 * 6)(*b'ABCDEF') 
b = string_at(addressof(h),sizeof(h)-Header.crc.size) 
print(b) 
h.crc = crc32(b) 
b = string_at(addressof(h),sizeof(h)) 
print(b) 

출력이 용액

b'\x01\x02\x03\x00ABCDEF' 
b'\x01\x02\x03\x00ABCDEF\xe7s\x85\xa6' 
+0

BIG 단점 가독성이다. 내 머리글은 128 바이트이므로 정말 엉망이고 읽을 수 없습니다 (ctypes 비교). 두 번째로'H' ='unsigned short' **로 기계에서 무엇을하겠습니까 **! = ** 16-bit? –

+0

@ S.R 당신은 "시도 구조체를 사용했지만 ** pragma ** 옵션을 찾을 수 없습니다"언급했다. 구조체를 전혀 사용하지 않으려면보다 구체적으로 작성하십시오. 어쨌든 ctypes 솔루션을 보여주기 위해 업데이트되었습니다. –

+0

@MarekTolonen 제 의견으로는 두 옵션 모두 파이썬 코드의 나머지 부분만큼 읽기 쉽지 않습니다. 하지만 마침내 네이티브'struct'를 사용했습니다. –

관련 문제