ctypes: Get full contents of character array

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • overdrigzed@gmail.com

    #1

    ctypes: Get full contents of character array

    Hello!

    I wanted to get the full contents of a character array stored in a
    struct, i.e.
    _fields_ = [...("array", c_char * 12)...]
    however, ctypes seems to try to return struct.array as a Python string
    rather than a character array, and stops as soon as it encounters a
    null within the character array.

    I ended up having to define a dummy struct
    class dummystruct(Str ucture):
    _fields_ = []

    and declare array as:
    ("array", dummystruct)

    then use string_at(byref (struct.array), 12).

    Is this really the best way of doing it? Is there no better way to
    work around ctypes 'guess what you want' behaviour?

    Thanks in advance,
    Rodrigo
  • Aaron \Castironpi\ Brady

    #2
    Re: ctypes: Get full contents of character array

    On Sep 12, 6:38 pm, overdrig...@gma il.com wrote:
    Hello!
    >
    I wanted to get the full contents of a character array stored in a
    struct, i.e.
    _fields_ = [...("array", c_char * 12)...]
    however, ctypes seems to try to return struct.array as a Python string
    rather than a character array, and stops as soon as it encounters a
    null within the character array.
    >
    I ended up having to define a dummy struct
    class dummystruct(Str ucture):
        _fields_ = []
    >
    and declare array as:
    ("array", dummystruct)
    >
    then use string_at(byref (struct.array), 12).
    >
    Is this really the best way of doing it? Is there no better way to
    work around ctypes 'guess what you want' behaviour?
    >
    Thanks in advance,
    Rodrigo
    Rodrigo,

    If you have the option to change your declaration to c_byte* 12, you
    have more options. This example prints the null character you wanted.

    from ctypes import *
    import struct
    class S( Structure ):
    _fields_= [
    ( 'array', c_byte* 12 )
    ]
    s= S()

    #initialize
    struct.pack_int o( '7s', s.array, 0, 'abc\x00def' )

    #prototype and call PyString_FromSt ringAndSize
    prototype= PYFUNCTYPE( py_object, POINTER( c_byte ), c_size_t )
    PyString_FromSt ringAndSize= prototype( ( "PyString_FromS tringAndSize",
    pythonapi ) )
    x= PyString_FromSt ringAndSize( s.array, 12 )
    print repr( x )

    #prototype and call PyString_FromSt ring for contrast
    prototype= PYFUNCTYPE( py_object, POINTER( c_byte ) )
    PyString_FromSt ring= prototype( ( "PyString_FromS tring", pythonapi ) )
    x= PyString_FromSt ring( s.array )
    print repr( x )

    /Output:

    'abc\x00def\x00 \x00\x00\x00\x0 0'
    'abc'

    Comment

    • overdrigzed@gmail.com

      #3
      Re: ctypes: Get full contents of character array

      On Sep 13, 6:45 am, "Aaron \"Castironpi \" Brady"
      <castiro...@gma il.comwrote:
      On Sep 12, 6:38 pm, overdrig...@gma il.com wrote:
      >
      >
      >
      >
      >
      >
      >
      Hello!
      >
      I wanted to get the full contents of a character array stored in a
      struct, i.e.
      _fields_ = [...("array", c_char * 12)...]
      however,ctypess eems to try to return struct.array as a Python string
      rather than a character array, and stops as soon as it encounters a
      null within the character array.
      >
      I ended up having to define a dummy struct
      class dummystruct(Str ucture):
          _fields_ = []
      >
      and declare array as:
      ("array", dummystruct)
      >
      then use string_at(byref (struct.array), 12).
      >
      Is this really the best way of doing it? Is there no better way to
      work aroundctypes'gu ess what you want' behaviour?
      >
      Thanks in advance,
      Rodrigo
      >
      Rodrigo,
      >
      If you have the option to change your declaration to c_byte* 12, you
      have more options.  This example prints the null character you wanted.
      >
      fromctypesimpor t *
      import struct
      class S( Structure ):
          _fields_= [
              ( 'array', c_byte* 12 )
          ]
      s= S()
      >
      #initialize
      struct.pack_int o( '7s', s.array, 0, 'abc\x00def' )
      >
      #prototype and call PyString_FromSt ringAndSize
      prototype= PYFUNCTYPE( py_object, POINTER( c_byte ), c_size_t )
      PyString_FromSt ringAndSize= prototype( ( "PyString_FromS tringAndSize",
      pythonapi ) )
      x= PyString_FromSt ringAndSize( s.array, 12 )
      print repr( x )
      >
      #prototype and call PyString_FromSt ring for contrast
      prototype= PYFUNCTYPE( py_object, POINTER( c_byte ) )
      PyString_FromSt ring= prototype( ( "PyString_FromS tring", pythonapi ) )
      x= PyString_FromSt ring( s.array )
      print repr( x )
      >
      /Output:
      >
      'abc\x00def\x00 \x00\x00\x00\x0 0'
      'abc'
      Great - and thank you for replying so fast! I found that [chr(x) for x
      in struct.array] with array as a c_byte * 12 did what I needed.

      Comment

      Working...