Iterable Ctypes Struct

mark.seagoe at gmail.com mark.seagoe at gmail.com
Wed Feb 11 19:32:41 CET 2009


On Feb 11, 9:01 am, mark.sea... at gmail.com wrote:
> On Feb 10, 9:52 pm, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
> wrote:
>
>
>
>
>
> > En Wed, 11 Feb 2009 00:31:26 -0200, <mark.sea... at gmail.com> escribió:
>
> > > I like the ability to access elements of a struct such as with ctypes
> > > Structure:
> > >>>> myStruct.elementName1
> > > 4
>
> > > What I like about it is there are no quotes needed.
>
> > > What I don't like about it is that it's not iterable:
> > >>>> for n in myStruct:  <== gives error
> > >>>>    print n
>
> > > I don't want to force the end user to have preknowledge of the element
> > > names.
>
> > Note that those names are available as the _fields_ class attribute
>
> > > Has anyone subclassed ctypes Structure based class to be iterable?
> > > Before a noob starts trying to do this, is it possible?  How to
> > > approach it?
>
> > The easiest way would be to define __getitem__ accepting index 0, 1, 2...  
> > until the last defined field.
> > Seehttp://docs.python.org/reference/datamodel.html#object.__getitem__
>
> > <code>
> >  from ctypes import Structure
>
> > class IterableStructure(Structure):
> >    def __getitem__(self, i):
> >      if not isinstance(i, int):
> >        raise TypeError('subindices must be integers: %r' % i)
> >      return getattr(self, self._fields_[i][0])
>
> > </code>
>
> > This was tested as much as you see here:
>
> > py> from ctypes import c_int
> > py>
> > py> class POINT(IterableStructure):
> > ...     _fields_ = [("x", c_int),
> > ...                 ("y", c_int)]
> > ...
> > py> point = POINT(10, 20)
> > py> print point.x, point.y
> > 10 20
> > py> for field in point:
> > ...   print field
> > ...
> > 10
> > 20
> > py> print list(point)
> > [10, 20]
>
> > --
> > Gabriel Genellina
>
> Thanks very much, Gabriel.  This is very good start for me.
> This works for predefined class.  How about a situation where the
> fields are added dynamically (as from reading in from an xml file).
> For example, if I were to now add another element:
>
> >>> point.z = 30
> >>> print list(point)
> [10, 20]
> >>> dir(point)
>
> ['__class__', '__ctypes_from_outparam__', '__delattr__', '__
> dict__', '__doc__', '__getattribute__', '__getitem__', '__ha
> sh__', '__init__', '__module__', '__new__', '__reduce__', '_
> _reduce_ex__', '__repr__', '__setattr__', '__str__', '__weak
> ref__', '_b_base_', '_b_needsfree_', '_fields_', '_objects',
>  'x', 'y', 'z']
>
> I don't know why the iterator (where ever it is) didn't get
> incremented.  Thanks for any insight.
>
> Mark- Hide quoted text -
>
> - Show quoted text -

I tinkered with it and think I have viable solution.
I need to append a new member to _fields_ before writing it,
then it seems to work.

>>> p._fields_.append(('z', c_int))
>>> point.z = 30
>>> print 'List:', list(p)
List: [10, 20, 30]

Awesome.  Thanks!



More information about the Python-list mailing list