2011-05-11 15 views
10

Estoy tratando de empacar algunos datos int sin firmar en un búfer de cadenas creado usando ctypes.create_string_buffer.Python: Cómo empacar diferentes tipos de datos en un búfer de cadenas usando struct.pack_into

Aquí es el siguiente segmento de código, y un ejemplo de funcionamiento que muestra el error on codepad:

import struct 
import ctypes 
import binascii 

buf = ctypes.create_string_buffer(16) 
struct.pack_into("=I=I=I", buf, 0, 1, 2, 3) 
print binascii.hexlify(buf) 

Esto produce el siguiente error:

... 
struct.error: bad char in struct format 

La documentación no se refiere a si se puede empacar datos de diferentes tipos si el buffer subyacente es de un tipo C específico. En este caso, tratando de empacar datos int sin firmar en un búfer de cadena con un tipo subyacente de c_char. ¿Alguien sabe de una solución para hacer esto, o hay una manera específica de crear un búfer que puede empacar cualquier tipo de datos?

Respuesta

12

No se supone que prefijar cada especificador de salida con el código de los '='. Sólo decir que una vez:

struct.pack_into("=III", buf, 0, 1, 2, 3) 

Esto produce:

01000000020000000300000000000000 
+0

Gracias. De alguna manera me perdí esa pieza crítica de lectura en el módulo docco :). – snap

1

procedimiento operativo estándar: Lea el mensaje de error.

"formato malo de char en struct" significa lo que dice.

Procedimiento de operación estándar: Consulte los documentos. Here dice "el primer [mi énfasis] carácter de la cadena de formato se puede utilizar para indicar el orden de bytes, el tamaño y la alineación de los datos empaquetados" y pasa a la lista = como una posibilidad. La siguiente sección (Formato de Caracteres) enumera muchas cartas incluyendo I.

Conclusión: su cadena de formato debe ser "=III".

Nota: El problema no tiene nada que ver con el búfer de destino en absoluto, por no hablar de su subyacente Tipo C:

>>> import struct 
>>> struct.pack("=I=I=I", 1, 2, 3) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
struct.error: bad char in struct format 
>>> struct.pack("=III", 1, 2, 3) 
'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00' 
>>> 
+1

De hecho, no creo que sea un mensaje de error muy bueno. No te dice qué personaje es "malo" y, de hecho, el personaje "malo" es en realidad un personaje permitido (simplemente sucede que solo es válido al principio de la cadena). –

3

Lo siento por resucitar viejo tema, pero me da el punto de "chasquido" - bienestar golpeado por hábito de fondo probablemente similar.

"el primer carácter de la cadena de formato se puede utilizar para indicar el orden de bytes, el tamaño y la alineación de los datos empaquetados" Acepto. Sin embargo: (?)

  • documentación de Python deliberadamente omiten ni un solo ejemplo de uso de formateadores de orden (Todos los ejemplos asumen un nativo orden de bytes, el tamaño y la alineación con una máquina-big endian.)
  • se puede suponer (como yo y probablemente complemento hice), que "III" se compone de tres cadenas de formato y nos puede dar formato a cada uno de ellos a voluntad. De ahí =I=I=I. Yo me tiro en el pie después de acostumbrarse a array.pack de Ruby, donde uno puede libremente Orden de cambios a lo largo de la expresión (equivalente de Ruby es I_I_I_ en este caso, como selector de orden viene después del tipo).

Por lo tanto supongo que podría ser bueno para agregar unas cuantas líneas a struct.pack/docs de desempaquetado, dando ejemplos de orden & uso de relleno (MEH, el relleno me golpeó aún más difícil ... Yo podría vivir con el fin nativa , pero el relleno arruinó mi protocolo).

+2

Si tiene una nueva pregunta, por favor, haga clic en el botón [Ask Question] (http://stackoverflow.com/questions/ask). Si tiene suficiente reputación, [puede votar] (http://stackoverflow.com/privileges/vote-up) la pregunta. Alternativamente, "star" como favorito y se te notificará cualquier nueva respuesta. – Jack

+0

No es una _NEW_ pregunta. Después de ver esta publicación, resolví mi problema. Es solo una nota, que los documentos de Python no están claros, por ejemplo para personas del mundo de Ruby, sobre este tema. –

+0

Entiendo, pero Stackoverflow no es en realidad un foro con * topics/threads *, sino más bien un sitio de preguntas y respuestas ... – Jack

Cuestiones relacionadas