Interconvert a ctypes.Structure to/from a binary string?
Nick Craig-Wood
nick at craig-wood.com
Mon Aug 4 07:32:56 EDT 2008
Andrew P. Lentvorski, Jr. <bsdder at gmail.com> wrote:
> On Aug 1, 11:35 pm, Andrew Lentvorski <bs... at allcaps.org> wrote:
> > Basically, I'd like to use the ctypes module as a much more descriptive
> > "struct" module.
> >
> > Is there a way to take a ctypes.Structure-based class and convert it
> > to/from a binary string?
> >
> > Thanks,
> > -a
>
> After chugging through the ctypes source code, I found that I can
> abuse ctypes into doing what I want.
>
> Here is how I did it. I can abuse
> string_at(addressof(SomeCtypesClass), length) to get a binary string
> out of ctypes while I use:
>
> def analyze_elf_header(binaryData):
> headerSize = ctypes.sizeof(Elf32_Ehdr)
> header = Elf32_Ehdr()
>
> # Abuse ctypes to initialize from a string
> bb = ctypes.create_string_buffer(binaryData[0:headerSize])
> ctypes.memmove(ctypes.addressof(header), ctypes.addressof(bb),
> headerSize)
>
> To jam stuff into a ctypes class. This seems like an oversight in the
> module though. It would really be better if the class itself had
> methods to init from/produce to a binary string.
>
> However, I would prefer that somebody who actually knows ctypes to
> weigh in here with comments about what I did.
I have found myself doing this quite a bit with ctypes. It is common
to get a block of data in which represents a stream of structures
which have to be unpicked and made into ctypes structs before use.
Making that stream is an equal challenge.
I've found a couple of ways of doing it.
Setup
>>> from ctypes import *
>>> class A(Structure):
... _fields_ = [("x", c_int)]
...
>>> packet="\x02\x01\x00\x00"
Eg to make a struct from a string
>>> a = cast(packet, POINTER(A)).contents
>>> a.x
258
>>>
Or (this is identical to your method)
>>> a = A()
>>> a.x
0
>>> memmove(addressof(a), packet, sizeof(a))
3083811008L
>>> a.x
258
I think the second of those methods is promoted by the ctypes
documentation. I'm not sure about the lifetimes of the .contents in
the first method!
And the reverse
>>> string_at(addressof(a), sizeof(a))
'\x02\x01\x00\x00'
>>>
Which I think is probably acceptable...
Some to/from binary methods would be nice, or failing that an explicit
section in the docs!
--
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick
More information about the Python-list
mailing list