diff options
-rw-r--r-- | doc/_templates/index.html | 4 | ||||
-rw-r--r-- | doc/compiling.rst | 2 | ||||
-rw-r--r-- | doc/contents.rst | 1 | ||||
-rw-r--r-- | doc/faq.rst | 22 | ||||
-rw-r--r-- | doc/tutorial/bindinglibfoo.rst | 77 | ||||
-rw-r--r-- | doc/tutorial/buildingthebinding.rst | 131 | ||||
-rw-r--r-- | doc/tutorial/globalheader.rst | 36 | ||||
-rw-r--r-- | doc/tutorial/images/generatorworkings.png | bin | 0 -> 37257 bytes | |||
-rw-r--r-- | doc/tutorial/images/generatorworkings.svg | 392 | ||||
-rw-r--r-- | doc/tutorial/introduction.rst | 32 | ||||
-rw-r--r-- | doc/tutorial/libfoo.rst | 69 | ||||
-rw-r--r-- | doc/tutorial/typesystemcreation.rst | 136 | ||||
-rw-r--r-- | libshiboken/shiboken.pc.in | 1 |
13 files changed, 892 insertions, 11 deletions
diff --git a/doc/_templates/index.html b/doc/_templates/index.html index 09486d7ee..cdbdee9b7 100644 --- a/doc/_templates/index.html +++ b/doc/_templates/index.html @@ -4,7 +4,7 @@ <div class="section"> <h1>{{ project }} {{ version }}</h1> - <p>{{ project }} is a plugin for Generator Runner, this generator generates CPython code instead of boost::python code as BoostPythonGenerator does.</p> + <p>{{ project }} is a plugin (front-end) for Generator Runner. It generates CPython code instead of boost::python code as BoostPythonGenerator does. This way the overall size of PySide bindings can be drastically reduced.</p> <h2>Documentation</h2> <table class="contentstable" align="center" style="margin-left: 30px"><tr> @@ -13,6 +13,8 @@ <span class="linkdescr">for a complete overview</span></p> <p class="biglink"><a class="biglink" href="{{ pathto("faq") }}">FAQ</a><br/> <span class="linkdescr">answers for frequent asked questions</span></p> + <p class="biglink"><a class="biglink" href="{{ pathto("tutorial/introduction") }}">Tutorial</a><br/> + <span class="linkdescr">start here</span></p> <p class="biglink"><a class="biglink" href="{{ pathto("commandlineoptions") }}">Command line options</a><br/> <span class="linkdescr">explains the few flags used to change {{ project }} behaviour</span></p> <p class="biglink"><a class="biglink" href="{{ pathto("typesystemvariables") }}">Type System Variables</a><br/> diff --git a/doc/compiling.rst b/doc/compiling.rst index d9ce2be4d..7958d573b 100644 --- a/doc/compiling.rst +++ b/doc/compiling.rst @@ -18,5 +18,5 @@ Building and installing ^^^^^^^^^^^^^^^^^^^^^^^ To build and install just follow the generic cmake instructions in -section cmake-primer. +section `cmake-primer <http://www.pyside.org/docs/pyside/howto-build/cmake-primer.html>`_. diff --git a/doc/contents.rst b/doc/contents.rst index 85751f6fc..f7fb39b8c 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -5,6 +5,7 @@ Table of contents :maxdepth: 3 faq.rst + tutorial/introduction.rst commandlineoptions.rst typesystemvariables.rst codeinjectionsemantics.rst diff --git a/doc/faq.rst b/doc/faq.rst index e854f4360..77e0fbdfc 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -11,11 +11,17 @@ General What is Shiboken? ----------------- -Shiboken is a GeneratorRunner plugin that outputs C++ code for CPython extensions. +Shiboken is a `GeneratorRunner <http://www.pyside.org/home-binding/binding-generator>`_ +plugin that outputs C++ code for CPython extensions. The first version of PySide +had source code based on Boost templates. It was easier to produce code but a +paradigm change was needed, as the next question explains. -Here the name generator refers actually to a program composed of a set of -*generator classes* that output different resources based on information -contained inside C++ header files. +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. Creating bindings ================= @@ -38,10 +44,10 @@ What do I have to do to create my bindings? .. todo: put link to typesystem documentation Most of the work is already done by the API Extractor. The developer creates -a typesystem 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. +a `typesystem <http://www.pyside.org/docs/apiextractor/typesystem.html>`_ 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. Is there any recommended build system? -------------------------------------- diff --git a/doc/tutorial/bindinglibfoo.rst b/doc/tutorial/bindinglibfoo.rst new file mode 100644 index 000000000..b12e53f0c --- /dev/null +++ b/doc/tutorial/bindinglibfoo.rst @@ -0,0 +1,77 @@ +.. highlight:: xml + +.. _gentut-bindinglibfoo: + +Binding libfoo using Shiboken +============================= + +In order to create bindings for a library based on Qt4 a number of components +must be available on the system. + + + Qt4 library (with headers and pkg-config .pc files for development -- the + ``-dev`` packages in a Debian distribution). + + Qt4 Python bindings made with :program:`shiboken`. + + Typesystems for the Qt4 Python bindings. + + Headers for the library to be bound. + +With the items listed above the developer must write the components from +where the generator will gather information to create the binding source code. + + + Typesystem file describing the way the binding must be done. + + **global.h** including all the **libfoo** headers and defining required macros. + + A build system to direct the process of generating, compiling and linking the + binding. + +The directory structure for the binding project could be something like the tree +shown below: + +:: + + foobinding/ + |-- data/ + `-- module_dir/ + `-- glue/ + + +The **data** directory should contain the **global.h** and the typesystem +file. This typesystem need to refer to the ones used to create the Qt4 bindings, +commonly located on **/usr/share/PySide/typesystem**, the exact location +can be checked with pkg-config: + +:: + + $ pkg-config pyside --variable=typesystemdir + + +The **module_dir** directory is the place where the sources generated should +be placed. It starts empty except for the build instructions file (Makefile, +Makefile.am, CMakeLists.txt, etc). The realname of this directory must be the +same written in the typesystem file: + +:: + + <typesystem package="module_dir"> + + +If there is any need for handwritten source code longer than a couple of lines, +making them unconfortable to be put on the typesystem xml file, the sources +could be orderly placed in a **glue** directory, also referred in the +new binding typesystem. + +When writing the typesystem file (more on this later) there is no need to refer +to the other required typesystem files with absolute paths, the locations where +they can be found could be passed to the generator through a command line +option (``--typesystem-paths=PATH1:PATH2:[...]``) or the environment variable +**TYPESYSTEMPATH**. + +For **libfoo** no glue code will be needed so this directory is not used, +the other directories are created with proper names. + +:: + + foobinding/ + |-- data/global.h + | `-- typesystem_foo.xml + `-- foo/ + `-- Makefile + diff --git a/doc/tutorial/buildingthebinding.rst b/doc/tutorial/buildingthebinding.rst new file mode 100644 index 000000000..d03010ca4 --- /dev/null +++ b/doc/tutorial/buildingthebinding.rst @@ -0,0 +1,131 @@ +.. _gentut-buildingthebinding: + +Building The Binding +==================== + +As mentioned before the build system used must perform the following tasks +in the correct order: + + + Gather data about locations of headers and external needed typesystems. + + Run the generator with the correct parameters. + + Compile and link the binding. + +The first and last are the usual, being the second the only novelty in the +process. + +Running the Generator +--------------------- + +The generator is called with the following parameters and options: + +:: + + $ generatorrunner --generatorSet=shiboken \ + global_headers.h \ + --include-paths=$(PATHS_TO_HEADERS)) \ + --typesystem-paths=$(PATHS_TO_TYPESYSTEMS) \ + --output-directory=. \ + typesystem.xml + +Notice that the variables for include and typesystem paths could be determined +at build time with the pkg-config tool. + +Collecting information with pkg-config +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Qt4 bindings include compile and build information through the pkg-config +mechanism. The pkg-config name for Qt4 Python bindings is **pyside** and a +simple ``pkg-config pyside --cflags --libs`` will retrieve the information +needed to build the new binding. + +The Qt4 bindings file ``pyside.pc`` for the use of pkg-config requires +the ``.pc`` files from Qt4 to be installed. If the library is in an unusual +location, e.g. ``/opt/qt46``, remember to export it to the ``PKG_CONFIG_PATH`` +environment variable. +For example: ``export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/opt/qt46/lib/pkgconfig`` + +There is a vital information also available through pkg-config: +the **typesystemdir** variable. It is used like this: +``pkg-config pyside --variable=typesystemdir`` This provides information +where to find the typesystem files used to create the Qt4 bindings, and as said +before the binding being created needs this to complement its own binding +information for the generation proccess. + +Makefile +-------- + +Below is a plain Makefile for the binding project. + +**foobinding/foo/Makefile** +:: + + LIBFOO_DIR = ../../libfoo + LIBS = `python-config --libs` \ + -lpyside \ + -lfoo -L$(LIBFOO_DIR) + CXXFLAGS = -I/usr/share/qt4/mkspecs/linux-g++ -I. \ + -I$(LIBFOO_DIR) \ + -I`pkg-config --variable=includedir pyside`/QtCore/ \ + -I`pkg-config --variable=includedir QtCore` \ + -I`pkg-config --variable=includedir QtGui` \ + -I`pkg-config --variable=includedir QtCore`/.. \ + -I`python-config --includes` \ + `pkg-config pyside --cflags` \ + `pkg-config shiboken --cflags` + + QT4TYPESYSTEM_DIR = "/usr/share/PySide/typesystem/" + QT4HEADER_DIRS = `pkg-config --variable=includedir QtCore`:`pkg-config --variable=includedir QtCore`/.. + + SOURCES = foo_module_wrapper.cpp math_wrapper.cpp + OBJECTS = foo_module_wrapper.o math_wrapper.o + + all: generate compile link + + generate: + generatorrunner --generatorSet=shiboken \ + ../data/global.h \ + --include-paths=$(LIBFOO_DIR):$(QT4HEADER_DIRS):/usr/include \ + --typesystem-paths=../data:$(QT4TYPESYSTEM_DIR) \ + --output-directory=.. \ + ../data/typesystem_foo.xml + + compile: $(SOURCES) + g++ -Wall -fPIC -DPIC $(CXXFLAGS) -c foo_module_wrapper.cpp + g++ -Wall -fPIC -DPIC $(CXXFLAGS) -c math_wrapper.cpp + + link: + g++ -shared -Wl,-soname,foo.so -o foo.so $(LIBS) $(OBJECTS) + + test: + LD_LIBRARY_PATH=$(LIBFOO_DIR):$LD_LIBRARY_PATH python -c \ + "import PySide.QtCore; import foo; print dir(foo); m = foo.Math(); print \"5 squared is %d\" % m.squared(5)" + + clean: + rm -rf *.o *.so *.?pp *.log *.h + +Keep in mind that the Makefile above expects the ``libfoo`` and +``foobinding`` directories to be in the same level in the directory +hierarchy, remember to change any path references accordingly if +you choose to change things. + +Testing the Binding +------------------- +Now compile the binding with ``make``: + +:: + + $ cd foobinding/foo + $ make + +To test if the new binding is working (it can pass the build phase but still +blow up at runtime) start up a Python terminal and import it by the name. + +:: + + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/libfoo/shared/object/dir + $ export PYTHONPATH=$PYTHONPATH:/path/to/foo/python/module/file/dir + $ python + >> import foo + >> print dir(foo) + >> m = foo.Math() + >> print m.squared(5) diff --git a/doc/tutorial/globalheader.rst b/doc/tutorial/globalheader.rst new file mode 100644 index 000000000..7e853f8c2 --- /dev/null +++ b/doc/tutorial/globalheader.rst @@ -0,0 +1,36 @@ +.. highlight:: cpp + +.. _gentut-globalheader: + +The Global Header +================= + +Besides the information provided by the typesystem, the generator needs to +gather more data from the library headers containing the classes to be exposed +in Python. If there is a header that include all the others (or just one, as is +the case of **libfoo**) this could be passed directly to the generator. + +If such a file is not available, or only a subset of the library is desired, or +if some flags must be defined before parsing the library headers, then a +``global.h`` file must be provided. + +The use of a ``global.h`` file is preferred if some macros must be defined +before the parser gather data from the headers. For example, if ``NULL`` is not +defined and it is used as a default paramater for some constructor or method, +the parser will not recognize it. + +To solve this create a ``global.h`` including all the desired headers and the +defined (and undefined) flags as follows: + +**foobinding/data/global.h** +:: + + #undef QT_NO_STL + #undef QT_NO_STL_WCHAR + + #ifndef NULL + #define NULL 0 + #endif + + #include <foo.h> + diff --git a/doc/tutorial/images/generatorworkings.png b/doc/tutorial/images/generatorworkings.png Binary files differnew file mode 100644 index 000000000..d35a565ff --- /dev/null +++ b/doc/tutorial/images/generatorworkings.png diff --git a/doc/tutorial/images/generatorworkings.svg b/doc/tutorial/images/generatorworkings.svg new file mode 100644 index 000000000..85a7782af --- /dev/null +++ b/doc/tutorial/images/generatorworkings.svg @@ -0,0 +1,392 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="680" + height="280" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="generatorworkings.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + inkscape:export-filename="generatorworkings.png" + inkscape:export-xdpi="86.970001" + inkscape:export-ydpi="86.970001" + version="1.0"> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0" + refX="0" + id="Arrow1Lstart" + style="overflow:visible"> + <path + id="path4293" + d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" + transform="matrix(0.8,0,0,0.8,10,0)" /> + </marker> + <linearGradient + inkscape:collect="always" + id="linearGradient3235"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3237" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3239" /> + </linearGradient> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Lend" + style="overflow:visible"> + <path + id="path3282" + d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" + transform="matrix(-0.8,0,0,-0.8,-10,0)" /> + </marker> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="6.1230318e-14 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3235" + id="linearGradient3241" + x1="-29.816929" + y1="320.97046" + x2="191.17912" + y2="322.7244" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + gridtolerance="10000" + guidetolerance="10" + objecttolerance="10" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.4420481" + inkscape:cx="361.95624" + inkscape:cy="122.34225" + inkscape:document-units="px" + inkscape:current-layer="g3297" + showgrid="false" + inkscape:window-width="1279" + inkscape:window-height="944" + inkscape:window-x="391" + inkscape:window-y="38" + showguides="true" + inkscape:guide-bbox="true"> + <sodipodi:guide + orientation="1,0" + position="-228.99296,-21.575354" + id="guide3165" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(291.86879,-366.35864)"> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="324.86121" + y="308.08389" + id="text3395" + transform="translate(-28.960129,110.67739)"><tspan + sodipodi:role="line" + id="tspan3397" + x="324.86121" + y="308.08389" /></text> + <g + id="g3254"> + <g + id="g3297" + transform="translate(15,11.795533)"> + <rect + style="fill:#e4fae3;fill-opacity:0.65882353;stroke:#8eff89;stroke-width:0.52055138;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3609" + width="323.15158" + height="216.66933" + x="-151.9006" + y="364.42294" + ry="7.354454" + rx="5.3701153" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline" + d="M 195.16416,473.16835 L 149.88745,473.08346" + id="path3285" + inkscape:connector-type="polyline" + sodipodi:nodetypes="cc" + inkscape:connection-start="#g3276" /> + <g + id="g3276" + transform="translate(-47.379381,-25.682818)"> + <rect + ry="11.816782" + rx="12.0209" + y="462.87637" + x="242.78513" + height="72.257683" + width="163.85461" + id="rect2461" + style="fill:#9dcdf9;fill-opacity:1;stroke:#0084ff;stroke-width:0.48317167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text2463" + y="494.80786" + x="324.45514" + style="font-size:144px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + style="font-size:22px;text-align:center;text-anchor:middle" + y="494.80786" + x="324.45514" + id="tspan2465" + sodipodi:role="line">binding</tspan><tspan + style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;font-family:FreeMono;-inkscape-font-specification:FreeMono" + y="519.56543" + x="324.45514" + sodipodi:role="line" + id="tspan3018">source code</tspan></text> + </g> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline" + d="M -130.41272,567.21015 L -180.20217,584.91297" + id="path3054" + inkscape:connector-type="polyline" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline" + d="M -129.57075,528.12072 L -181.18287,504.96225" + id="path3056" + inkscape:connector-type="polyline" + sodipodi:nodetypes="cc" /> + <g + id="g3147" + transform="translate(74.301071,9.8268847)"> + <g + transform="translate(62.764666,-13.729771)" + id="g2986"> + <rect + style="fill:#fafcc5;fill-opacity:1;stroke:#f9ff00;stroke-width:0.3511245;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2970" + width="115.38314" + height="55.650036" + x="-430.1297" + y="481.9653" + rx="11.184198" + ry="13.895926" /> + <text + xml:space="preserve" + style="font-size:144px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="-371.96939" + y="505.29422" + id="text2972"><tspan + id="tspan2976" + sodipodi:role="line" + x="-371.96939" + y="505.29422" + style="font-size:16px;text-align:center;text-anchor:middle">typesystem</tspan><tspan + id="tspan2980" + sodipodi:role="line" + x="-371.96939" + y="525.29419" + style="font-size:16px;text-align:center;text-anchor:middle">descriptions</tspan></text> + </g> + <g + transform="translate(74.533053,61.297656)" + id="g3020"> + <rect + style="fill:#fafcc5;fill-opacity:1;stroke:#f9ff00;stroke-width:0.36426121;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3022" + width="91.833252" + height="75.250854" + x="-418.35477" + y="472.16489" + rx="9.1466599" + ry="12.17058" /> + <text + xml:space="preserve" + style="font-size:144px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="-372.64865" + y="494.13867" + id="text3024"><tspan + id="tspan3026" + sodipodi:role="line" + x="-372.64865" + y="494.13867" + style="font-size:16px;text-align:center;text-anchor:middle">custom</tspan><tspan + id="tspan3028" + sodipodi:role="line" + x="-372.64865" + y="513.88837" + style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;font-family:FreeMono;-inkscape-font-specification:FreeMono">source</tspan><tspan + id="tspan3030" + sodipodi:role="line" + x="-372.64865" + y="536.38837" + style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;font-family:FreeMono;-inkscape-font-specification:FreeMono">code</tspan></text> + </g> + </g> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline" + d="M -40.946515,396.85213 L -179.16818,396.16834" + id="path3098" + inkscape:connector-type="polyline" + sodipodi:nodetypes="cc" /> + <g + id="g3141" + transform="translate(66.255107,-6.2939423)"> + <rect + ry="11.897643" + rx="9.5758715" + y="381.30014" + x="-342.70132" + height="47.647366" + width="98.790642" + id="rect2415" + style="fill:#fafcc5;fill-opacity:1;stroke:#f9ff00;stroke-width:0.30063155;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text2417" + y="401.08865" + x="-293.63803" + style="font-size:144px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + style="font-size:16px;text-align:center;text-anchor:middle" + y="401.08865" + x="-293.63803" + id="tspan2419" + sodipodi:role="line">library</tspan><tspan + style="font-size:16px;text-align:center;text-anchor:middle" + y="421.08865" + x="-293.63803" + sodipodi:role="line" + id="tspan2949">headers</tspan></text> + </g> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline" + d="M 33.165609,503.00316 L 32.819729,546.19947" + id="path3167" + inkscape:connector-type="polyline" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline" + d="M 33.145722,443.9261 L 32.799842,391.41316" + id="path3169" + inkscape:connector-type="polyline" + sodipodi:nodetypes="cc" /> + <g + id="g2944" + transform="translate(85.554958,3.1233551)"> + <rect + rx="6.8840375" + ry="10.365664" + y="371.05527" + x="-125.40932" + height="44.903805" + width="101.06483" + id="rect3625" + style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.36750945;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + transform="scale(1.0000266,0.9999734)" + id="text3627" + y="401.12787" + x="-75.810593" + style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + style="font-size:21.29199791px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + y="401.12787" + x="-75.810593" + sodipodi:role="line" + id="tspan3697">Parser</tspan></text> + </g> + <g + id="g3093" + transform="translate(-22.960524,10.08797)"> + <rect + ry="8.5151205" + rx="9.4630651" + y="433.92093" + x="9.3588104" + height="58.626995" + width="163.91852" + id="rect2446" + style="fill:#b2d7b5;fill-opacity:1;stroke:#34ff34;stroke-width:0.20534486;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.69008268" /> + <text + id="text2448" + y="457.49274" + x="90.813187" + style="font-size:144px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + style="font-size:22px;font-weight:bold;text-align:center;text-anchor:middle" + y="457.49274" + x="90.813187" + id="tspan2450" + sodipodi:role="line">Generator</tspan><tspan + style="font-size:22px;font-weight:bold;text-align:center;text-anchor:middle" + y="484.99274" + x="90.813187" + sodipodi:role="line" + id="tspan3340">Backend</tspan></text> + </g> + <g + id="g3160" + transform="translate(94.301071,19.633862)"> + <rect + rx="5.7330456" + ry="8.3964748" + y="506.2883" + x="-225.62247" + height="44.764942" + width="192.46243" + id="rect2933" + style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.50637114;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + transform="scale(1.0000266,0.9999734)" + id="text2935" + y="534.47565" + x="-128.93036" + style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + style="font-size:21.29199791px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + y="534.47565" + x="-128.93036" + sodipodi:role="line" + id="tspan2937">TypeDatabase</tspan></text> + </g> + </g> + </g> + </g> +</svg> diff --git a/doc/tutorial/introduction.rst b/doc/tutorial/introduction.rst new file mode 100644 index 000000000..40240f80a --- /dev/null +++ b/doc/tutorial/introduction.rst @@ -0,0 +1,32 @@ +Binding Generation Tutorial +*************************** + +This tutorial intends to describe the process of binding creation with +Shiboken and using a very simple Qt4 based library will be used as an +example. + +The image below shows the inputs needed to generate the binding source code. + +.. image:: images/generatorworkings.png + +Putting in words, the user provides the headers for the library along with a +`typesystem <http://www.pyside.org/docs/apiextractor/typesystem.html>`_ file +describing how the classes will be exposed in the target language, as well as +any needed custom source code to be merged with the generated source code. + +This tutorial will go through the steps needed to have the binding +ready to be imported and used from a Python program. The tutorial +source code is available as a tar ball `here <../_static/bindingexample.tar.gz>`_. + +**NOTE:** the binding generator is intended to be used with Qt4 based libraries +only, at least for the time being. + +.. toctree:: + :maxdepth: 3 + + libfoo + bindinglibfoo + typesystemcreation + globalheader + buildingthebinding + diff --git a/doc/tutorial/libfoo.rst b/doc/tutorial/libfoo.rst new file mode 100644 index 000000000..bad6b014a --- /dev/null +++ b/doc/tutorial/libfoo.rst @@ -0,0 +1,69 @@ +.. highlight:: cpp + +.. _gentut-libfoo: + +Creating the foo library +========================= + +In this section it will be presented the code and the build instructions for a +very simple Qt4 based library. It will be used as the subject for this tutorial. + +The Source Code +--------------- + +There is only one class on this foo library plus a ``.pro`` file which means +that the build system used will be `qmake <http://doc.qt.nokia.com/4.6/qmake-manual.html>`_ +based. + +Put the files below in a directory called **libfoo**. Be aware that this +directory will be referred by the binding Makefile presented in a next section +of this tutorial. If you want to use other names or paths change the binding +Makefile accordingly. Blind copy'n'paste shortens your life. + +**libfoo/foo.h** +:: + + #ifndef FOO_H + #define FOO_H + + #include <QtCore/QtCore> + + class Math : public QObject + { + Q_OBJECT + public: + Math() {} + virtual ~Math() {} + int squared(int x); + }; + #endif // FOO_H + + +**libfoo/foo.cpp** +:: + + #include "foo.h" + + int Math::squared(int x) + { + return x * x; + } + + +**libfoo/foo.pro** +:: + + TEMPLATE = lib + TARGET = foo + DEPENDPATH += . + INCLUDEPATH += . + HEADERS += foo.h + SOURCES += foo.cpp + +To build the lib: + +:: + + $ cd libfoo + $ qmake + $ make diff --git a/doc/tutorial/typesystemcreation.rst b/doc/tutorial/typesystemcreation.rst new file mode 100644 index 000000000..538222337 --- /dev/null +++ b/doc/tutorial/typesystemcreation.rst @@ -0,0 +1,136 @@ +.. highlight:: xml + +.. _gentut-typesystem: + +Creating the Typesystem Description +=================================== + +The typesystem is an specification used when mapping a C++ based library onto a +corresponding Python module. The specification is a handwritten XML document +listing the types that will be available in the generated binding, modifications +to classes and function signatures to better suit the target language, +and listing the components that should be rejected for the binding. + +**PySide** uses a typesystem format similar to the one used by **QtJambi** and +**QtScript**, thoroughly described in the page *"The Qt Jambi Type System"*. [#]_ + +The divergences between **PySide** and QtScript/QtJambi typesystems will be +highlighted whenever they appear. Things to be aware of when writing +a typesystem will be also mentioned. + +Describing **libfoo** for Python Audiences +------------------------------------------ + +All typesystem files start with the root ``typesystem`` tag. The +``package`` attribute carries the name of the package as it will be seen +from Python. + +Right after that, all the typesystem files providing information required for +the generation process are included in the same fashion as header files in C. + +**foobinding/data/typesystem_foo.xml** +:: + + <?xml version="1.0"?> + <typesystem package="foo"> + <load-typesystem name="typesystem_core.xml" generate="no"/> + <object-type name="Math"/> + </typesystem> + + +The inclusion of other typesystem files is achieved with the +``load-typesystem`` tag. The ``generate`` attribute must be set to ``"no"`` +otherwise the generator will try to create more source code for the already +existing bindings included for reference. + +The C++ classes derived from **QObject** intended to be exposed in the target +language are described with ``object-type`` tags. + + +For this example binding just specifying the name of the class does the trick, +since the generator system will automatically catch the methods with arguments +and return value of known types. These types can be described in the same +typesystem file or in the ones referenced with the ``load-typesystem`` tag. + +In more complex situations method signatures can be changed or rejected with +other tags that can be checked out in the `typesystem <http://www.pyside.org/docs/apiextractor/typesystem.html>`_ +reference. + + +Other Common Cases and Differences +---------------------------------- + +What follows now is some common uses of the typesystem capabilities. All of them +can be seen in the Qt4 typesystem files. They are not used for this binding +tutorial example, so if you just want to have things working ASAP, move along. + +Templates +~~~~~~~~~ + +To ease the process of writing custom code for the binding, recurring pieces of +code can be turned generic with the typesystem template mechanism. +They are declared in a way similar to this snippet: + +:: + + <template name="only_bool*_fix"> + bool ok; + %RETURN_TYPE retval = self.%FUNCTION_NAME(&ok); + </template> + +And is used as in this example: + +:: + + <inject-code class="native" position="beginning"> + <insert-template name="only_bool*_fix"/> + </inject-code> + + +The ``typesystem_template.xml`` file from the Qt4 bindings can be used as a +good resource for examples of this. Check also the QtJambi documentation on +typesystem templates. [#]_ + +Non-QObject Derived Classes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Even in a Qt4 based library it is common to find classes that doesn't +pertain to the QObject hierarchy, these must be declared as ``value-type``: + +:: + + <value-type name="RectOrSomethingLikeThat"/> + + +Unused Tags +~~~~~~~~~~~ + +Some tags defined in the QtScript/QtJambi typesystem has no effect in **PySide** +typesystem, they are: + + + conversion-rule + + argument-map + +Changes to ``"inject-code"`` Tag +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can pass a file name to the **inject-code** tag so the file contents will +be injected in the generated code. + +The ``class`` attribute value ``java`` was changed to ``target``, while +``native`` remained the same. + +Global Functions +~~~~~~~~~~~~~~~~ + +The BoostPythonGenerator supports global functions, you can also reject these functions using +the **rejection** tag like is done to reject classes. Just pass an empty string to +the class attribute. + +:: + + <rejection class="" function-name="qt_noop"/> + + +.. [#] http://doc.trolltech.com/qtjambi-4.4/html/com/trolltech/qt/qtjambi-typesystem.html +.. [#] http://doc.trolltech.com/qtjambi-4.4/html/com/trolltech/qt/qtjambi-typesystem.html#using-code-templates diff --git a/libshiboken/shiboken.pc.in b/libshiboken/shiboken.pc.in index 0920fb614..c188831d2 100644 --- a/libshiboken/shiboken.pc.in +++ b/libshiboken/shiboken.pc.in @@ -6,7 +6,6 @@ generator_location=@CMAKE_INSTALL_PREFIX@/bin/shiboken Name: shiboken Description: Support library for Python bindings created with Shiboken generator. -Requires: Python Version: @libshiboken_VERSION@ Libs: -L${libdir} -lpython Cflags: -I${includedir} |