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(&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 PySide@lists.pyside.org http://lists.pyside.org/listinfo/pyside