diff options
authorVenugopal Shivashankar <Venugopal.Shivashankar@qt.io>2018-11-14 15:04:00 +0100
committerVenugopal Shivashankar <Venugopal.Shivashankar@qt.io>2018-11-30 11:57:03 +0000
commit0a40640a1882dceb34f601dc818cd64c29612672 (patch)
parent81e7fd946f172df3e567a6caef463b559505b106 (diff)
Doc: Add an index page for Shiboken
Also document the samplebinding example. Change-Id: I2ee1fa6049ae672f5ab46df4d1eba411e69dc3c7 Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
-rw-r--r--sources/shiboken2/doc/images/icecream.pngbin0 -> 4272 bytes
-rw-r--r--sources/shiboken2/doc/images/qtforpython-underthehood.pngbin0 -> 19144 bytes
7 files changed, 280 insertions, 6 deletions
diff --git a/sources/pyside2/doc/index.rst b/sources/pyside2/doc/index.rst
index fa1daec00..27fefeb16 100644
--- a/sources/pyside2/doc/index.rst
+++ b/sources/pyside2/doc/index.rst
@@ -102,8 +102,7 @@ Qt Modules
Provides classes to create and use state machines from SCXML files.
|project| also comes with the
-:doc:`Shiboken2 <shiboken2:contents>` generator that outputs C++ code
-for CPython extensions.
+:doc:`Shiboken2 <shiboken2:index>` CPython binding code generator.
.. toctree::
:maxdepth: 2
diff --git a/sources/shiboken2/doc/conf.py.in b/sources/shiboken2/doc/conf.py.in
index 3ca8ac573..d3aa95c0b 100644
--- a/sources/shiboken2/doc/conf.py.in
+++ b/sources/shiboken2/doc/conf.py.in
@@ -39,7 +39,7 @@ source_suffix = '.rst'
source_encoding = 'utf-8'
# The master toctree document.
-#master_doc = 'contents'
+master_doc = 'index'
# General information about the project.
project = u'Shiboken'
@@ -137,7 +137,7 @@ html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes']
# Additional templates that should be rendered to pages, maps page names to
# template names.
-html_additional_pages = { 'index' : 'index.html'}
+#html_additional_pages = { 'index' : 'index.html'}
# If false, no module index is generated.
html_use_modindex = False
diff --git a/sources/shiboken2/doc/contents.rst b/sources/shiboken2/doc/contents.rst
index 24adb1c68..a0b40effb 100644
--- a/sources/shiboken2/doc/contents.rst
+++ b/sources/shiboken2/doc/contents.rst
@@ -1,11 +1,10 @@
Table of contents
.. toctree::
- :numbered:
:maxdepth: 3
- faq.rst
+ samplebinding.rst
@@ -15,3 +14,4 @@ Table of contents
+ faq.rst
diff --git a/sources/shiboken2/doc/images/icecream.png b/sources/shiboken2/doc/images/icecream.png
new file mode 100644
index 000000000..41d1a25fa
--- /dev/null
+++ b/sources/shiboken2/doc/images/icecream.png
Binary files differ
diff --git a/sources/shiboken2/doc/images/qtforpython-underthehood.png b/sources/shiboken2/doc/images/qtforpython-underthehood.png
new file mode 100644
index 000000000..64e30b1c5
--- /dev/null
+++ b/sources/shiboken2/doc/images/qtforpython-underthehood.png
Binary files differ
diff --git a/sources/shiboken2/doc/index.rst b/sources/shiboken2/doc/index.rst
new file mode 100644
index 000000000..4cc5b204e
--- /dev/null
+++ b/sources/shiboken2/doc/index.rst
@@ -0,0 +1,28 @@
+Shiboken the Binding Generator
+Shiboken is the CPython-based binding code generator for C or C++ libraries.
+It uses an ApiExtractor library to parse the C or C++ headers and get the
+type information, using Clang. The library can also be used to parse non-Qt
+projects. The following diagram summarizes Shiboken's role in the PySide
+.. image:: images/qtforpython-underthehood.png
+A typesystem file (XML) is used to specify the types to be exposed to Python
+and to apply modifications to properly represent and manipulate the types in
+the Python World. For example, you can remove and add methods to certain types,
+and also modify the arguments of each method. Such actions are inevitable to
+properly handle the data structures or types.
+The final outcome of this process is a set of wrappers written in CPython,
+which can be used as a module in your python code.
+Refer to the following topics for more information and examples:
+.. toctree::
+ :maxdepth: 1
+ overview
+ samplebinding
+ contents
diff --git a/sources/shiboken2/doc/samplebinding.rst b/sources/shiboken2/doc/samplebinding.rst
new file mode 100644
index 000000000..2e0311092
--- /dev/null
+++ b/sources/shiboken2/doc/samplebinding.rst
@@ -0,0 +1,247 @@
+SampleBinding Example
+The example showcases how you can generate CPython-based binding code for a
+C++ library using Shiboken. The C++ library is called Universe,
+with two classes: Icecream and Truck. Icecreams are characterized
+by their flavor, and Truck serves as a vehicle of Icecream distribution for
+kids in a neighborhood.
+First, let's look at the definition of the two classes:
+.. code-block::
+ :caption: icecream.h
+ class Icecream
+ {
+ public:
+ Icecream(const std::string &flavor);
+ virtual Icecream *clone();
+ virtual ~Icecream();
+ virtual const std::string getFlavor();
+ private:
+ std::string m_flavor;
+ };
+and then truck.h:
+.. code-block:: c++
+ :caption: truck.h
+ class Truck {
+ public:
+ Truck(bool leaveOnDestruction = false);
+ Truck(const Truck &other);
+ Truck& operator=(const Truck &other);
+ ~Truck();
+ void addIcecreamFlavor(Icecream *icecream);
+ void printAvailableFlavors() const;
+ bool deliver() const;
+ void arrive() const;
+ void leave() const;
+ void setLeaveOnDestruction(bool value);
+ void setArrivalMessage(const std::string &message);
+ private:
+ void clearFlavors();
+ bool m_leaveOnDestruction = false;
+ std::string m_arrivalMessage = "A new icecream truck has arrived!\n";
+ std::vector m_flavors;
+ };
+Here is a summary of what the Universe library includes:
+* The Icecream polymorphic type, which is intended to be overridden.
+* The getFlavor() method returns the flavor depending on the actual derived
+ type.
+* The Truck value type that contains owned pointers, hence the copy
+ constructor.
+* Truck stores the Icecream objects in a vector, which can be modified via
+ addIcecreamFlavor().
+* The Truck’s arrival message can be customized using setArrivalMessage().
+* The deliver() method tells us if the ice cream delivery was successful.
+Shiboken typesystem
+Now that the library definitions are in place, Shiboken generator needs a header
+file that includes the types we are interested in:
+.. code-block:: c
+ :caption: bindings.h
+ #ifndef BINDINGS_H
+ #define BINDINGS_H
+ #include "icecream.h"
+ #include "truck.h"
+ #endif // BINDINGS_H
+In addition, Shiboken also requires an XML-based typesystem file that defines the
+relationship between C++ and Python types:
+.. code-block::
+ :caption: bindings.xml
+ <?xml version="1.0"?>
+ <typesystem package="Universe">
+ <primitive-type name="bool"/>
+ <primitive-type name="std::string"/>
+ <object-type name="Icecream">
+ <modify-function signature="clone()">
+ <modify-argument index="0">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ </object-type>
+ <value-type name="Truck">
+ <modify-function signature="addIcecreamFlavor(Icecream*)">
+ <modify-argument index="1">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+ </typesystem>
+The first important thing to notice here is that we declare "bool" and
+"std::string" as primitive types. These types are used by some of the C++
+methods as parameters or return types, so Shiboken must know about them.
+It can then generate relevant conversion code between C++ and Python, although
+most C++ primitive types are handled by Shiboken without additional code.
+Next, we declare the two aforementioned classes. One of them as an
+“object-type” and the other as a “value-type”. The main difference is that
+object-types are passed around in generated code as pointers, whereas
+value-types are copied (value semantics).
+By specifying the names of these classes in the typesystem file, Shiboken
+automatically tries to generate bindings for all methods of those
+classes. You need not mention all the methods manually in the XML file, unless
+you want to modify them.
+Object ownership rules
+Shiboken cannot magically know who is responsible for freeing the C++ objects
+allocated in the Python code. It can guess, but it’s not always correct. There
+can be cases where Python should release the C++ memory when the ref count
+of the Python object becomes zero. It should never delete the C++ object assuming
+that it will not be deleted by the C++ library or maybe it’s parented to another
+object (like QWidgets).
+In our case, the :code:`clone()` method is only called inside the C++ library,
+and we assume that the C++ code takes care of releasing the cloned object.
+As for :code:`addIcecreamFlavor()`, we know that a Truck owns the Icecream
+object, and will remove it once the Truck is destroyed. That's why the
+ownership is set to “c++” in the typesystem file, so that the C++ objects
+are not deleted when the corresponding Python names go out of scope.
+To build the Universe custom library and then generate bindings for it, use
+the :file:`CMakeLists.txt` file provided with the example. You can reuse the
+file for your own libraries with minor changes.
+Now, run the command :command:`cmake .` from the prompt to configure the
+project and build with the toolchain of your choice (we recommend the
+‘(N)Makefiles’ generator though).
+As a result, you end up with two shared libraries:
+:file:`libuniverse.(so/dylib/dll)` and :file:`Universe.(so/pyd)`. The former is
+the custom C++ library, and the latter is the Python module that can be
+imported in your Python script.
+Refer to the :file:`README.md` file for more details about the Windows-specific
+build instructions.
+Using the Python module
+The following script uses the Universe module, derives a few types from
+Icecream, implements virtual methods, instantiates objects, and much more:
+.. code-block:: python
+ :caption: main.py
+ from Universe import Icecream, Truck
+ class VanillaChocolateIcecream(Icecream):
+ def __init__(self, flavor=""):
+ super(VanillaChocolateIcecream, self).__init__(flavor)
+ def clone(self):
+ return VanillaChocolateIcecream(self.getFlavor())
+ def getFlavor(self):
+ return "vanilla sprinked with chocolate"
+ class VanillaChocolateCherryIcecream(VanillaChocolateIcecream):
+ def __init__(self, flavor=""):
+ super(VanillaChocolateIcecream, self).__init__(flavor)
+ def clone(self):
+ return VanillaChocolateCherryIcecream(self.getFlavor())
+ def getFlavor(self):
+ base_flavor = super(VanillaChocolateCherryIcecream, self).getFlavor()
+ return base_flavor + " and a cherry"
+ if __name__ == '__main__':
+ leave_on_destruction = True
+ truck = Truck(leave_on_destruction)
+ flavors = ["vanilla", "chocolate", "strawberry"]
+ for f in flavors:
+ icecream = Icecream(f)
+ truck.addIcecreamFlavor(icecream)
+ truck.addIcecreamFlavor(VanillaChocolateIcecream())
+ truck.addIcecreamFlavor(VanillaChocolateCherryIcecream())
+ truck.arrive()
+ truck.printAvailableFlavors()
+ result = truck.deliver()
+ if result:
+ print("All the kids got some icecream!")
+ else:
+ print("Aww, someone didn't get the flavor they wanted...")
+ if not result:
+ special_truck = Truck(truck)
+ del truck
+ print("")
+ special_truck.setArrivalMessage("A new SPECIAL icecream truck has arrived!\n")
+ special_truck.arrive()
+ special_truck.addIcecreamFlavor(Icecream("SPECIAL *magical* icecream"))
+ special_truck.printAvailableFlavors()
+ special_truck.deliver()
+ print("Now everyone got the flavor they wanted!")
+ special_truck.leave()
+After importing the classes from the Universe module, it derives two types from
+Icecream for different “flavors”. It then creates a :code:`truck` to deliver
+some regular flavored Icecreams and two special ones.
+If the delivery fails, a new truck is created with the old flavors copied over,
+and a new *magical* flavor that will surely satisfy all customers.
+The script above shows how to derive from C++ types, override virtual methods,
+create and destroy objects, and more. Try running it to see if the ice creams
+are delivered.
+.. note::
+ You can find the sources for this example under
+ :file:`<PYTHON_ENV_ROOT>/site-packages/lib/PySide2/examples/samplebinding`.
+Refer to the following topics for detailed information about using Shiboken:
+ * :doc:`Shiboken module <shibokenmodule>`
+ * :doc:`Type System Variables <typesystemvariables>`
+ * :doc:`User Defined Type Conversion <typeconverters>`
+ * :doc:`Object ownership <ownership>`
+ * :doc:`Frequently Asked Questions <faq>`