Acceso a campos de bits mientras se leen / escriben estructuras de datos binarios

Estoy escribiendo un analizador para un formato binario. Este formato binario involucra diferentes tablas que, de nuevo, están en formato binario y contienen diferentes tamaños de campo (en algún lugar entre 50 y 100 de ellas).

La mayoría de estas estructuras tendrán campos de bits y se verán como estos cuando se representen en C:

struct myHeader { unsigned char fieldA : 3 unsigned char fieldB : 2; unsigned char fieldC : 3; unsigned short fieldD : 14; unsigned char fieldE : 4 } 

Me encontré con el módulo de estructura, pero me di cuenta de que su resolución más baja era un byte y no un poco, de lo contrario, el módulo era el adecuado para este trabajo.

Sé que los campos de bits son compatibles con ctypes, pero no estoy seguro de cómo conectar las estructuras de ctypes que contienen campos de bits aquí.

Mi otra opción es manipular los bits yo mismo y alimentarlos en bytes y usarlos con el módulo de estructura, pero como tengo cerca de 50-100 tipos diferentes de tales estructuras, escribir el código para eso se vuelve más propenso a errores. También me preocupa la eficiencia, ya que esta herramienta podría usarse para analizar gigabytes grandes de datos binarios.

Gracias.

El uso de cadenas de bits (que usted menciona que están viendo) debería ser lo suficientemente fácil de implementar. Primero en crear algunos datos para decodificar:

 >>> myheader = "3, 2, 3, 14, 4" >>> a = bitstring.pack(myheader, 1, 0, 5, 1000, 2) >>> a.bin '00100101000011111010000010' >>> a.tobytes() '%\x0f\xa0\x80' 

Y luego decodificarlo de nuevo es solo

 >>> a.readlist(myheader) [1, 0, 5, 1000, 2] 

Su principal preocupación podría ser la velocidad. La biblioteca está bien optimizada en Python, pero eso no es tan rápido como lo sería una biblioteca en C.

No he probado rigurosamente esto, pero parece funcionar con tipos sin firmar (edición: también funciona con tipos de bytes / bytes firmados).

Edición 2: Esto es realmente impredecible. Depende de la forma en que el comstackdor de la biblioteca empacó los bits en la estructura, que no está estandarizada. Por ejemplo, con gcc 4.5.3 funciona siempre que no use el atributo para empaquetar la estructura, es decir, __attribute__ ((__packed__)) (así que en lugar de 6 bytes se empaquetará en 4 bytes, que puede verificar con __alignof__ y sizeof ). Puedo hacer que casi funcione agregando _pack_ = True a la definición de estructura de ctypes, pero falla para fieldE. notas de gcc: “El desplazamiento del campo de bits empaquetado ‘fieldE’ ha cambiado en GCC 4.4”.

 import ctypes class MyHeader(ctypes.Structure): _fields_ = [ ('fieldA', ctypes.c_ubyte, 3), ('fieldB', ctypes.c_ubyte, 2), ('fieldC', ctypes.c_ubyte, 3), ('fieldD', ctypes.c_ushort, 14), ('fieldE', ctypes.c_ubyte, 4), ] lib = ctypes.cdll.LoadLibrary('C/bitfield.dll') hdr = MyHeader() lib.set_header(ctypes.byref(hdr)) for x in hdr._fields_: print("%s: %d" % (x[0], getattr(hdr, x[0]))) 

Salida:

 fieldA: 3 fieldB: 1 fieldC: 5 fieldD: 12345 fieldE: 9 

DO:

 typedef struct _MyHeader { unsigned char fieldA : 3; unsigned char fieldB : 2; unsigned char fieldC : 3; unsigned short fieldD : 14; unsigned char fieldE : 4; } MyHeader, *pMyHeader; int set_header(pMyHeader hdr) { hdr->fieldA = 3; hdr->fieldB = 1; hdr->fieldC = 5; hdr->fieldD = 12345; hdr->fieldE = 9; return(0); }