Issue5042
Created on 2009-01-24 16:04 by jaraco, last changed 2009-09-18 19:48 by theller.
|
msg80457 - (view) |
Author: Jason R. Coombs (jaraco) |
Date: 2009-01-24 16:04 |
|
When trying to create a sub-subclass of a ctypes.Structure, the behavior
is not as expected.
An executable example that describes the problem in detail and
demonstrates the issue is available at
http://paste.turbogears.org/paste/29555 and also attached.
The failing behavior is near the beginning, following the description.
Three unsuccessful workarounds follow.
The expected behavior is found at the end, where a final workaround has
been implemented.
Can this behavior be improved in subsequent releases of ctypes? If not,
can ctypes at least support the workaround natively (perhaps by
providing a method in the Structure class that performs the workaround
and can be called by a sub-subclass during __init__)?
|
|
msg92792 - (view) |
Author: Thomas Heller (theller) |
Date: 2009-09-17 19:53 |
|
The problem is the implementation of the current __init__ method, in
Modules/_ctypes/_ctypes.c, line 4024. Rewritten in Python, and slightly
simplified it looks like this:
def __init__(self, *args, **kw):
"""The current BUGGY __init__ method"""
names = [f[0] for f in self._fields_]
for n, v in zip(names, args):
setattr(self, n, v)
for n, v in kw.iteritems():
setattr(self, n, v)
It assigns positional parameters to the names found in the _fields_ list
of the subclass, but it should look up all the _fields_ definitions in
all the superclasses, too. Working pseudo Python code:
def __init__(self, *args, **kw):
"""This is how the Structure's __init__method SHOULD be"""
if args:
names = []
for tp in self.__class__.mro()[2::-1]:
for n, _ in tp._fields_:
names.append(n)
for n, v in zip(names, args):
setattr(self, n, v)
for n, v in kw.iteritems():
setattr(self, n, v)
Now, I don't really want to write the above code in C ;-).
|
|
msg92793 - (view) |
Author: Jason R. Coombs (jaraco) |
Date: 2009-09-17 20:00 |
|
Heh. Me neither.
Is it possible to use something like Cython to generate the C code?
|
|
msg92794 - (view) |
Author: Jason R. Coombs (jaraco) |
Date: 2009-09-17 20:09 |
|
That was easier than I thought. The generated code is _ugly_ but it did
seem to be able to generate it.
I created init.pyx
{{{
class X(object):
def __init__(self, *args, **kw):
"""This is how the Structure's __init__method SHOULD be"""
if args:
names = []
for tp in self.__class__.mro()[2::-1]:
for n, _ in tp._fields_:
names.append(n)
for n, v in zip(names, args):
setattr(self, n, v)
for n, v in kw.iteritems():
setattr(self, n, v)
}}}
Then, ran cython init.pyx and got the attached file.
Is that any help?
|
|
msg92816 - (view) |
Author: Thomas Heller (theller) |
Date: 2009-09-18 08:25 |
|
> Is that any help?
Not really ;-).
Here is a patch I just wrote - it must still be checked for correctness,
and tests for it must be added. I hope the comment in the code explains
how it works. ctypes-structinit.patch
|
|
msg92838 - (view) |
Author: Thomas Heller (theller) |
Date: 2009-09-18 19:48 |
|
I've commited a slightly changed patch plus a test.
trunk: 74917, py3k: 74918, release26-maint: 74919, release31-maint: 74920.
|
|
| Date |
User |
Action |
Args |
| 2009-09-18 19:48:44 | theller | set | status: open -> closed resolution: fixed versions:
- Python 2.5 |
| 2009-09-18 19:48:24 | theller | set | messages:
+ msg92838 |
| 2009-09-18 08:25:09 | theller | set | files:
+ ctypes-structinit.patch keywords:
+ patch messages:
+ msg92816
|
| 2009-09-17 20:09:06 | jaraco | set | files:
+ init.c
messages:
+ msg92794 |
| 2009-09-17 20:00:13 | jaraco | set | messages:
+ msg92793 |
| 2009-09-17 19:53:37 | theller | set | messages:
+ msg92792 |
| 2009-09-17 19:49:03 | theller | set | versions:
+ Python 3.1, Python 2.7, Python 3.2, - Python 3.0 |
| 2009-01-24 16:04:18 | jaraco | create | |
|