Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Iterable Ctypes Struct

Reply
Thread Tools

Iterable Ctypes Struct

 
 
mark.seagoe@gmail.com
Guest
Posts: n/a
 
      02-11-2009
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.
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?

Thx,
Mark
 
Reply With Quote
 
 
 
 
Gabriel Genellina
Guest
Posts: n/a
 
      02-11-2009
En Wed, 11 Feb 2009 00:31:26 -0200, <(E-Mail Removed)> 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.
See http://docs.python.org/reference/dat...ct.__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

 
Reply With Quote
 
 
 
 
mark.seagoe@gmail.com
Guest
Posts: n/a
 
      02-11-2009
On Feb 10, 9:52*pm, "Gabriel Genellina" <(E-Mail Removed)>
wrote:
> En Wed, 11 Feb 2009 00:31:26 -0200, <(E-Mail Removed)> 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
 
Reply With Quote
 
mark.seagoe@gmail.com
Guest
Posts: n/a
 
      02-11-2009
On Feb 11, 9:01*am, (E-Mail Removed) wrote:
> On Feb 10, 9:52*pm, "Gabriel Genellina" <(E-Mail Removed)>
> wrote:
>
>
>
>
>
> > En Wed, 11 Feb 2009 00:31:26 -0200, <(E-Mail Removed)> 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!
 
Reply With Quote
 
mark.seagoe@gmail.com
Guest
Posts: n/a
 
      02-11-2009
In last post, I mixed code w/ 'p' and 'point'. Should be:

>>> point._fields_.append(('z', c_int))
>>> point.z = 30
>>> print 'List:', list(point)


List: [10, 20, 30]
 
Reply With Quote
 
Gabriel Genellina
Guest
Posts: n/a
 
      02-11-2009
En Wed, 11 Feb 2009 16:32:41 -0200, <(E-Mail Removed)> escribió:
> On Feb 11, 9:01*am, (E-Mail Removed) wrote:
>> On Feb 10, 9:52*pm, "Gabriel Genellina" <(E-Mail Removed)>
>> wrote:
>> > En Wed, 11 Feb 2009 00:31:26 -0200, <(E-Mail Removed)> escribió:

>>
>> > > I like the ability to access elements of a struct such as with > >

>> ctypes
>> > > Structure:
>> > > What I don't like about it is that it's not iterable:
>> > > I don't want to force the end user to have preknowledge of the > >

>> element
>> > > names.


[recipe using _fields_]

>> 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).

> 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]


Yes, that's the way to add a new field -- but you have to do that before
creating the first instance. Anywy, this is somewhat strange for a ctypes
Structure. Usually its memory layout is fixed and mandated by the
library/format/whatever you're trying to bind to.
You are not using it as a generic attribute container, are you? There are
better alternatives in that case.

--
Gabriel Genellina

 
Reply With Quote
 
mark.seagoe@gmail.com
Guest
Posts: n/a
 
      02-12-2009


Hi Gabriel;

Not sure what generic attribute container is. I am reading in from
xml file
all reg names for a chip. So then I'd be able to use python scripts
to
access the regs. So eventually this class will get subclassed w/ hw
access
instead of just saving in int. So I want to call this module
something like
"CHIP" which contains a struct. I add the "REG" struct objects as I
read
them in from xml file. The "REG" struct would have info about
address, # of
bits, type (RO, RW, etc).

Thx,
Mark


 
Reply With Quote
 
Marc 'BlackJack' Rintsch
Guest
Posts: n/a
 
      02-12-2009
On Wed, 11 Feb 2009 17:33:23 -0800, mark.seagoe wrote:

> Not sure what generic attribute container is. I am reading in from xml
> file all reg names for a chip.


Are you using instances of that class to interface C code or to read/
write data intended to be read or written by a C program? If not then
`ctypes` might be the wrong tool.

Ciao,
Marc 'BlackJack' Rintsch
 
Reply With Quote
 
mark.seagoe@gmail.com
Guest
Posts: n/a
 
      02-12-2009
On Feb 11, 5:51*pm, Marc 'BlackJack' Rintsch <(E-Mail Removed)> wrote:
> On Wed, 11 Feb 2009 17:33:23 -0800, mark.seagoe wrote:
> > Not sure what generic attribute container is. *I am reading in from xml
> > file all reg names for a chip.

>
> Are you using instances of that class to interface C code or to read/
> write data intended to be read or written by a C program? *If not then
> `ctypes` might be the wrong tool.
>
> Ciao,
> * * * * Marc 'BlackJack' Rintsch


It's accessing through USB so I'm also interfacing to Win32 drivers.
But at this higher level, since I'm somewhat new to Python so I'm not
aware of other classes which exist to allow accessing in the format
desired (without quotes and using dot notation):
classname.elementname1, instead of something like classname
["elementname1"]. It's just cosmetic, but I'd prefer the dot notation
without quotes for the end user experience of script writing later.
Is there something besides ctypes.Structure that would do that?

Thx,
Mark
 
Reply With Quote
 
Gabriel Genellina
Guest
Posts: n/a
 
      02-12-2009
En Thu, 12 Feb 2009 00:02:12 -0200, <(E-Mail Removed)> escribió:
> On Feb 11, 5:51*pm, Marc 'BlackJack' Rintsch <(E-Mail Removed)> wrote:
>> On Wed, 11 Feb 2009 17:33:23 -0800, mark.seagoe wrote:


>> > Not sure what generic attribute container is. *I am reading in from >

>> xml file all reg names for a chip.
>>
>> Are you using instances of that class to interface C code or to read/
>> write data intended to be read or written by a C program? *If not then
>> `ctypes` might be the wrong tool.

>
> It's accessing through USB so I'm also interfacing to Win32 drivers.
> But at this higher level, since I'm somewhat new to Python so I'm not
> aware of other classes which exist to allow accessing in the format
> desired (without quotes and using dot notation):
> classname.elementname1, instead of something like classname
> ["elementname1"]. It's just cosmetic, but I'd prefer the dot notation
> without quotes for the end user experience of script writing later.
> Is there something besides ctypes.Structure that would do that?


You don't need *anything* special to add attributes to an object in
Python. Even an empty class is enough:

py> class Struct(object):
.... pass # an empty class
....
py> s = Struct()
py> s.x = 10
py> s.y = 20
py> print s.x, s.y
10 20
py>

But since this thread started asking how to iterate over the attributes,
let's use a named tuple:

py> from collections import namedtuple
py> StructWithNames = namedtuple("StructWithNames", "x,y,z")
py> s = StructWithNames(10, 20, 30)
py> s.z
30
py> s
StructWithNames(x=10, y=20, z=30)
py> list(s)
[10, 20, 30]
py> for item in s: print item
....
10
20
30
py> s._fields
('x', 'y', 'z')

--
Gabriel Genellina

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can *common* struct-members of 2 different struct-types, that are thesame for the first common members, be accessed via pointer cast to either struct-type? John Reye C Programming 28 05-08-2012 12:24 AM
filter iterable based on predicate take from another iterable bernhard.voigt@gmail.com Python 2 12-10-2008 10:44 AM
WindowsXP/ CTypes - How to convert ctypes array to a string? dudeja.rajat@gmail.com Python 0 08-19-2008 10:20 AM
RE: [ctypes-users] [Ann] ctypes 0.9.0 released Henk Punt Python 0 07-23-2004 10:34 PM
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct)); Chris Fogelklou C Programming 36 04-20-2004 08:27 AM



Advertisments