PySide Binding Generator
The Shiboken binding generator is a utility that parses the headers for a given C/C++ library, generates a model, and modifies it based on XML typesystem files containing complementary semantic information, modifications, renamings, etc, in order to generate the binding source code (or documentation) for the target language for which it was written.
Binding Generators are created using the Generator Runner facilities, which are composed of the abstract Generator class, that must be extended by generator front-ends and build as loadable modules. The Generator Runner application is responsible for instantiating the API Extractor to parse the headers and binding information from the typesystem files, after that it will load and call the generator front-ends indicated by the user.
The Binding Generator Architecture is illustrated in the figure below.
C++ Bindings and PySide Bindings
Although written using Qt, Shiboken does not generate Qt dependent code for C++ libraries, with the exception of PySide Python binding, which relies on a base library (libpyside) to take care of a number of Qt-specific situations, like signal connection and calling. All generated C++ bindings share some common features, like wrapper-C++ object relationships, ownership, virtual methods, etc.
The generator scheme is shown below.
What is the binding generator?
Here the name generator refers actually to an application composed of a set of generator classes that output different source code files based on information contained inside C++ header files and XML description file(s). We call our generator Shiboken. You can find more details on the Binding Generator" and Shiboken pages.
Why did you switch from Boost.Python to Shiboken?
The main reason was the size reduction. Boost.Python makes excessive use of templates resulting in a significant increase of the binaries size. On the other hand, as Shiboken generates CPython code, the resulting binaries are smaller.
What are the dependencies of Shiboken?
Just QtCore and the API Extractor.
What is the API Extractor?
The API Extractor is a tool that parses C++ header files from a given library and merges the collected information with a description, written by the user in XML, of how it should expose to a high level target language. It actually started as a fork of QtScriptGenerator, which is a monolithic application composed of generator and extractor code, and we converted the former component to a library. QtScriptGenerator is itself a fork of the generator used to create the Qt Jambi bindings.
How API Extractor is used?
The API Extractor comes as a library that should be used by a generator front-end designed to output binding code for the desired high level target language.
What are the dependencies of API Extractor?
Just QtCore and QtXml.
Are there any similar tools around?
Py+ is very similar to our generator as it is now, except that other generator front-ends could be created to output binding codes of different approaches (CPython, Cython, ctypes, etc). There are QtScriptGenerator and Qt Jambi, but they are tied to their target languages.
Can I wrap non-Qt C+ libraries?
Of course, but make sure that those libraries support RTTI, as the runtime library (check question below) use it. Check the test bindings on Shiboken source code.
Is there any runtime dependency on the generated binding?
The runtime dependency for non-Qt bindings is ">Shiboken Shiboken runtime library, libshiboken, a library that takes care of the relationship between C++ objects and the associate Python wrappers and issues of object ownership. For PySide-based bindings, in addition to libshiboken, you'll need Qt libraries and libpyside, which handles Qt signals, slots and properties. libpyside is part of the PySide bindings.
The wrapped library should also support RTTI, as libshiboken uses it on the wrapped types.
What do I have to do to create my bindings?
Most of the work is already done by the API Extractor. The developer creates a type system file with any customization wanted in the generated code, like removing classes or changing method signatures. The generator will output the .h and .cpp files with the CPython code that will wrap the target library for python.
What is a type system file?
It is an XML description on how the C++ library should be exported to the target language of the binding. If any class, function or method must be renamed, a method parameter removed, a C++ type declared as convertible, a class not exported, any hand written code to be added and so on, the type system file is the place to put those changes. Various other changes can be described on the XML file, check the type system format reference and binding creation tutorial for more information.
But you told me that the generator would automate the task of binding generation and set me free of boring stuff! How lame is that?
Yes, we told you that, but it's kind of unavoidable to give some information to the system about the semantics of the library to be wrapped. There are subtle things like object ownership that the generator cannot discover by itself.
What about object ownership?
Sometimes a library method or function receives an object and becomes responsible for its life and death. The generator must be made aware of such behavior through the type system description. Let's use an example: an object is instantiated in the target language (being this object the wrapper of a C++ object), and passed as a parameter to a C++ wrapped function which destroys the underlying C++ object leaving the wrapper in a inconsistent state.
Writing XML files is boring, do you provide a tool to create the description files?
Not yet, but we have plans for a script that checks your library and create an initial type system XML for it, just to help starting a new binding project. We also have an idea for a graphical tool to present the classes, functions and other stuff from the library to be wrapped and let you check what should be exported, renamed, etc. But right now it is just an idea, since for the time being we will be focusing on stabilizing and improving the PySide bindings.
What is 'inject code'?
That's how we call customized code that will be injected into the generated code at specific locations. They are specified inside the type system.
Which build system do you recommend?
Although any would do, we like the CMake build system, which is used by API Extractor, binding generator and PySide. You can refer to the build files from any of those projects as examples to create yours.
Can I write closed-source bindings with the generator?
Yes, as long as you use a LGPL version of Qt, due to runtime requirements.
How can I document my project?
The binding generator can also generate the API documentation based on the C++ headers documentation using the qdoc syntax. Optionally you can inject documentation at specific parts. Like the inject code, the customized documentation is specified inside the type system.
Is there any current limitation within the generator/API Extractor?
The code snippets in function documentation and examples are still in C++ inside the generated documentation, and they should be altered using typesystem tags.