Interconvert a ctypes.Structure to/from a binary string?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andrew Lentvorski

    Interconvert a ctypes.Structure to/from a binary string?

    Basically, I'd like to use the ctypes module as a much more descriptive
    "struct" module.

    Is there a way to take a ctypes.Structur e-based class and convert it
    to/from a binary string?

    Thanks,
    -a
  • Uwe Schmitt

    #2
    Re: Interconvert a ctypes.Structur e to/from a binary string?

    On 2 Aug., 08:35, Andrew Lentvorski <bs...@allcaps. orgwrote:
    Basically, I'd like to use the ctypes module as a much more descriptive
    "struct" module.
    >
    Is there a way to take a ctypes.Structur e-based class and convert it
    to/from a binary string?
    >
    Thanks,
    -a
    My first idea was :

    from ctypes import *
    from pickle import *

    class T(Structure): pass

    print dumps(T())

    which raises an TypeError, "abstract class".

    And then I found

    Stay at the forefront of innovation with Osdir - Your go-to source for all things tech and entertainment.


    Greetings, Uwe

    Comment

    • Andrew P. Lentvorski, Jr.

      #3
      Re: Interconvert a ctypes.Structur e to/from a binary string?

      On Aug 1, 11:35 pm, Andrew Lentvorski <bs...@allcaps. orgwrote:
      Basically, I'd like to use the ctypes module as a much more descriptive
      "struct" module.
      >
      Is there a way to take a ctypes.Structur e-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(addre ssof(SomeCtypes Class), length) to get a binary string
      out of ctypes while I use:

      def analyze_elf_hea der(binaryData) :
      headerSize = ctypes.sizeof(E lf32_Ehdr)
      header = Elf32_Ehdr()

      # Abuse ctypes to initialize from a string
      bb = ctypes.create_s tring_buffer(bi naryData[0:headerSize])
      ctypes.memmove( ctypes.addresso f(header), ctypes.addresso f(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.

      Thanks,
      -a

      Comment

      • Nick Craig-Wood

        #4
        Re: Interconvert a ctypes.Structur e to/from a binary string?

        Andrew P. Lentvorski, Jr. <bsdder@gmail.c omwrote:
        On Aug 1, 11:35 pm, Andrew Lentvorski <bs...@allcaps. orgwrote:
        Basically, I'd like to use the ctypes module as a much more descriptive
        "struct" module.

        Is there a way to take a ctypes.Structur e-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(addre ssof(SomeCtypes Class), length) to get a binary string
        out of ctypes while I use:
        >
        def analyze_elf_hea der(binaryData) :
        headerSize = ctypes.sizeof(E lf32_Ehdr)
        header = Elf32_Ehdr()
        >
        # Abuse ctypes to initialize from a string
        bb = ctypes.create_s tring_buffer(bi naryData[0:headerSize])
        ctypes.memmove( ctypes.addresso f(header), ctypes.addresso f(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)).con tents
        >>a.x
        258
        >>>
        Or (this is identical to your method)
        >>a = A()
        >>a.x
        0
        >>memmove(addre ssof(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(add ressof(a), sizeof(a))
        '\x02\x01\x00\x 00'
        >>>
        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@craig-wood.com-- http://www.craig-wood.com/nick

        Comment

        Working...