[PySide] Announcing the new type converters

88 views
Skip to first unread message

Marcelo Lira

unread,
Dec 19, 2011, 12:32:38 PM12/19/11
to pys...@srvrec006.openbossa.org
Hi list,

at long last the new converters branch was merged into master. Viva!
In the old converters we relied completely in the C++ template mechanism,
and although useful this method has some annoying drawbacks. Allow me to remind
you how it used to work using an example. Suppose you have this QChar type that
you want to be converted to and from Python's string/unicode, in the type system
file we introduce it like this:

<primitive-type name="QChar">
<conversion-rule file="qchar_conversions.h"/>
</primitive-type>

The "qchar_conversions.h" contains this:

template<>
struct Converter<QChar>
{
static bool checkType(PyObject* pyObj) {
return Shiboken::String::check(pyObj) &&
(Shiboken::String::len(pyObj) == 1);
}
static bool isConvertible(PyObject* pyObj) {
return (Shiboken::String::check(pyObj) &&
(Shiboken::String::len(pyObj) == 1))
|| pyObj == Py_None
|| PyInt_Check(pyObj);
}
static QChar toCpp(PyObject* pyObj) {
if (Shiboken::String::check(pyObj) && (Shiboken::String::len(pyObj) == 1))
return QChar(Shiboken::Converter<char >::toCpp(pyObj));
else if (PyInt_Check(pyObj))
return QChar(Shiboken::Converter<int >::toCpp(pyObj));
return QChar();
}
static PyObject* toPython(const QChar& cppObj)
{
wchar_t c = (wchar_t)cppObj.unicode();
PyObject* pyObj = PyUnicode_FromWideChar(&c, 1);
return pyObj;
}
};


The generated binding code uses it like this:

QChar cppValue = Shiboken::Converter<QChar>::toCpp(pyValue);


The first problem is the size. Every module that uses this conversion
will have duplicated code inserted by the C++ compiler. The new converters
are not template based anymore, so their code appears only in the module
where they were declared, and passed around to modules that depend on them
(e.g. as QChar converter is defined in QtCore, but also used in QtGui and
others).

From the point of view of the generation, the converter code is a binary
blob that Shiboken knows only that converts a type, and nothing else. In
the example above, Shiboken doesn't know that the Python types str, int,
and None, may be converted to the C++ QChar. And boy, how good would be
to have that information sometimes.

Here's the new way of creating type converters:

<primitive-type name="QChar">
<conversion-rule>
<native-to-target>
wchar_t c = (wchar_t)%in.unicode();
return PyUnicode_FromWideChar(&amp;c, 1);
</native-to-target>
<target-to-native>
<add-conversion type="PyString"
check="Shiboken::String::checkChar(%in)">
char c = %CONVERTTOCPP[char](%in);
%out = %OUTTYPE(c);
</add-conversion>
<add-conversion type="PyInt">
int i = %CONVERTTOCPP[int](%in);
%out = %OUTTYPE(i);
</add-conversion>
<add-conversion type="Py_None">
%out = %OUTTYPE();
</add-conversion>
</target-to-native>
</conversion-rule>
</primitive-type>

Everything is done in the type system XML, which means that the generator
understands all pieces of data. The <native-to-target> section describes
how to go from C++ to Python, and the <target-to-native> section contains
descriptions of how to go from one or various Python types to one C++ type.
I'll not go into details for now, but it's clear that each of Python->C++
conversion is declared individually and is fully known by the Shiboken
generator.

Another thing, the generated code that deals with checking and converting
Python method arguments goes like this:

1. Ask if the given Python argument is convertible to the C++ argument
2. Convert the Python argument to the C++ value of the expected type

If you scroll back to the old template converter for QChar, you'll see that
the isConvertible function checks if the Python value is of the acceptable
types (this is step 1), and later the toCpp function checks for those types
again to select the method of conversion. There was no communication between
isConvertible and toCpp, as one would expect. Now, the isConvertible check
returns a pointer to the correct toCpp function, or NULL if the type is not
convertible. A simple improvement, but we have to enjoy the little things.

Then, there is the binding handling of Qt's signals. The signals demanded us
to provide converters "on the fly", and since the template converters weren't
flexible enough, we had to provide a intermediate layer in the form of
TypeResolvers, which wrapped around instances of template converters
and associated
them with the type names. They were a bit more than simple Adapters,
and thus added
some fat to the bindings. And we also ended up with two converter
systems: templates
and function pointers. The new converters are better suited to work with the
signal system, and the old TypeResolvers are also gone.

What else? The converter code now is treated like any other custom code, as the
ones introduced with the <inject-code> tag, and may make use of type
system templates
and variables (%CONVERTTOCPP, %OUTTYPE, etc).

All this makes the user defined converters more integrated with the
whole system,
and give more control to the Shiboken generator, which means more possibilities
for performance improvements and size shrinking.

That's all for now. The code is already in the mainline/master branch,
and I'll soon
post a migration path for everyone using Shiboken to generate their bindings.

Cheers,
Marcelo Lira
_______________________________________________
PySide mailing list
PyS...@lists.pyside.org
http://lists.pyside.org/listinfo/pyside

Николай

unread,
Dec 19, 2011, 4:36:57 PM12/19/11
to pys...@lists.openbossa.org
Can this new system be used for plain C code?

Niki
--
|  (\_/)  This is Bunny. Copy and paste
| (='.'=) Bunny into your signature to help
| (")_(") him gain world domination

Marcelo Lira

unread,
Dec 19, 2011, 6:39:52 PM12/19/11
to Николай, pys...@lists.openbossa.org
Yes, but the generated code will still link to libshiboken, which is C++.

anatoly techtonik

unread,
Dec 20, 2011, 11:42:06 AM12/20/11
to Marcelo Lira, pys...@lists.openbossa.org
I didn't use those features, but the stuff you've done sounds awesome.
--
anatoly t.

Marcelo Lira

unread,
Dec 20, 2011, 12:03:09 PM12/20/11
to anatoly techtonik, pys...@lists.openbossa.org
anatoly, thanks :)
Reply all
Reply to author
Forward
0 new messages