diff options
author | Venugopal Shivashankar <Venugopal.Shivashankar@qt.io> | 2018-11-14 15:04:00 +0100 |
---|---|---|
committer | Venugopal Shivashankar <Venugopal.Shivashankar@qt.io> | 2018-11-30 11:57:03 +0000 |
commit | 0a40640a1882dceb34f601dc818cd64c29612672 (patch) | |
tree | f69947c309a52113d7a1ed1b7829967774f073d7 /sources/shiboken2/doc | |
parent | 81e7fd946f172df3e567a6caef463b559505b106 (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>
Diffstat (limited to 'sources/shiboken2/doc')
-rw-r--r-- | sources/shiboken2/doc/conf.py.in | 4 | ||||
-rw-r--r-- | sources/shiboken2/doc/contents.rst | 4 | ||||
-rw-r--r-- | sources/shiboken2/doc/images/icecream.png | bin | 0 -> 4272 bytes | |||
-rw-r--r-- | sources/shiboken2/doc/images/qtforpython-underthehood.png | bin | 0 -> 19144 bytes | |||
-rw-r--r-- | sources/shiboken2/doc/index.rst | 28 | ||||
-rw-r--r-- | sources/shiboken2/doc/samplebinding.rst | 247 |
6 files changed, 279 insertions, 4 deletions
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 overview.rst + samplebinding.rst commandlineoptions.rst projectfile.rst typesystemvariables.rst @@ -15,3 +14,4 @@ Table of contents ownership.rst wordsofadvice.rst shibokenmodule.rst + faq.rst diff --git a/sources/shiboken2/doc/images/icecream.png b/sources/shiboken2/doc/images/icecream.png Binary files differnew file mode 100644 index 000000000..41d1a25fa --- /dev/null +++ b/sources/shiboken2/doc/images/icecream.png diff --git a/sources/shiboken2/doc/images/qtforpython-underthehood.png b/sources/shiboken2/doc/images/qtforpython-underthehood.png Binary files differnew file mode 100644 index 000000000..64e30b1c5 --- /dev/null +++ b/sources/shiboken2/doc/images/qtforpython-underthehood.png 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 +project. + +.. 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. + +Building +========= + +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>` |