[PyQt] sip_api_can_convert_to_type chokes on converting a Python list to a QLIst of enums.
Phil Thompson
phil at riverbankcomputing.com
Thu Jul 15 17:42:23 BST 2010
On Wed, 14 Jul 2010 10:42:42 +0200, Gerard Vermeulen <gav451 at gmail.com>
wrote:
> Hi,
>
> I have the following sip declaration (left some irrelevant
> ConvertToSubclass stuff out):
>
> class QwtPickerMachine
> {
> %TypeHeaderCode
> #include <qwt_picker_machine.h>
> %End // %TypeHeaderCode
>
> public:
> enum Command {
> Begin,
> Append,
> Move,
> End
> }; // enum Command
>
> virtual ~QwtPickerMachine();
> virtual QList<QwtPickerMachine::Command> transition(const
> QwtEventPattern&, const QEvent*) = 0;
> void reset();
> int state() const;
> void setState(int);
> protected:
> QwtPickerMachine();
> ..
> }
>
> And a Python demo program where QwtPicker::transition() is overridden:
>
> class PickerMachine(QwtPickerMachine):
>
> def __init__(self, *args):
> QwtPickerMachine.__init__(self, *args)
>
> # __init__()
>
> def transition(self, eventPattern, e):
> commands = []
> print commands
> # handle the mouse events
> if e.type() == QEvent.MouseButtonPress:
> if eventPattern.mouseMatch(QwtEventPattern.MouseSelect1, e):
> if self.state() == 0:
> commands.append(QwtPickerMachine.Begin)
> commands.append(QwtPickerMachine.Append)
> self.setState(1)
> elif e.type() == QEvent.MouseMove:
> if self.state != 0:
> commands.append(Qwt.QwtPickerMachine.Append)
> elif e.type() == QEvent.MouseButtonRelease:
> commands.append(QwtPickerMachine.End)
> self.setState(0)
> # handling of the keyboard events is left as an excercise
> print commands
> return commands # "return []" works.
> return []
>
> # transition()
>
> # class PickerMachine()
>
> And a modified siplib.c where
>
> printf("td_flags: %d; td_sipTypeName: %s\n", td->td_flags,
> sipTypeName(td));
>
> is added before the assert statement in sip_api_can_convert_to_type().
>
> My demo program fails in when siplib has to handle the list that is
> returned by PickerMachine.transition():
>
> 1. QList<QwtPickerMachine::Command>
> sipQwtPickerMachine::transition(const QwtEventPattern&,const QEvent *)
> (this=0x00f0bcd0)
> 2. []
> 3. meth_QwtEventPattern_mouseMatch()
> 4. td_flags: 16; td_sipTypeName: QMouseEvent
> 5. meth_QwtPickerMachine_state()
> 6. meth_QwtPickerMachine_setState()
> 7. [0, 1]
> 8. dealloc_QwtEventPattern()
> 9. td_flags: 2; td_sipTypeName: QList<QwtPickerMachine::Command>
> 10. td_flags: 3; td_sipTypeName: QwtPickerMachine::Command
> 11. python: siplib.c:7505: sip_api_can_convert_to_type: Assertion
> `(((td)->td_flags & 0x0007) == 0x0000) || (((td)->td_flags & 0x0007) ==
> 0x0002)' failed.
> 12. Aborted
>
> where line 2 and 7 are written by the print statements in the Python
> code above, line 4, 9, and 10 by the printf added to
> sip_api_can_convert_to_type() and the other lines by the sip tracing
> mechanism.
It's a fundamental and long-standing SIP design bug. The template argument
support doesn't distinguish between named enums and classes so it is using
%ConvertToTypeCode written for classes and applying it to an enum.
The workaround is to explicitly provide a %MappedType - see
QList<QLocale::Country> in qlocale.sip for an example.
Phil
More information about the PyQt
mailing list