From e0c29962e6f334452f0c9db2caaf6ed18065de85 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 17 Aug 2009 19:31:37 -0300 Subject: The End Is the Beginning Is the End --- doc/Makefile | 88 +++++ doc/_static/.gitignore | 0 doc/_templates/index.html | 34 ++ doc/_templates/layout.html | 10 + doc/compiling/cmake-primer.rst | 68 ++++ doc/compiling/compiling.rst | 9 + doc/compiling/setup-apiextractor.rst | 56 +++ doc/compiling/setup-generator.rst | 54 +++ doc/conf.py | 198 ++++++++++ doc/contents.rst | 10 + doc/dependency-pyqtb.svg | 600 ++++++++++++++++++++++++++++++ doc/faq.rst | 107 ++++++ doc/images/.directory | 3 + doc/images/bindinggen-development.png | Bin 0 -> 34333 bytes doc/images/boostgen.png | Bin 0 -> 153473 bytes doc/images/boostqtarch.png | Bin 0 -> 34257 bytes doc/overview.rst | 46 +++ doc/tutorial/bindinglibfoo.rst | 76 ++++ doc/tutorial/buildingthebinding.rst | 133 +++++++ doc/tutorial/globalheader.rst | 36 ++ doc/tutorial/images/generatorworkings.png | Bin 0 -> 37257 bytes doc/tutorial/images/generatorworkings.svg | 392 +++++++++++++++++++ doc/tutorial/introduction.rst | 31 ++ doc/tutorial/libfoo.rst | 68 ++++ doc/tutorial/typesystemcreation.rst | 136 +++++++ 25 files changed, 2155 insertions(+) create mode 100644 doc/Makefile create mode 100644 doc/_static/.gitignore create mode 100644 doc/_templates/index.html create mode 100644 doc/_templates/layout.html create mode 100644 doc/compiling/cmake-primer.rst create mode 100644 doc/compiling/compiling.rst create mode 100644 doc/compiling/setup-apiextractor.rst create mode 100644 doc/compiling/setup-generator.rst create mode 100644 doc/conf.py create mode 100644 doc/contents.rst create mode 100644 doc/dependency-pyqtb.svg create mode 100644 doc/faq.rst create mode 100644 doc/images/.directory create mode 100644 doc/images/bindinggen-development.png create mode 100644 doc/images/boostgen.png create mode 100644 doc/images/boostqtarch.png create mode 100644 doc/overview.rst create mode 100644 doc/tutorial/bindinglibfoo.rst create mode 100644 doc/tutorial/buildingthebinding.rst create mode 100644 doc/tutorial/globalheader.rst create mode 100644 doc/tutorial/images/generatorworkings.png create mode 100644 doc/tutorial/images/generatorworkings.svg create mode 100644 doc/tutorial/introduction.rst create mode 100644 doc/tutorial/libfoo.rst create mode 100644 doc/tutorial/typesystemcreation.rst (limited to 'doc') diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 000000000..69b857c58 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,88 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf _build/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html + @echo + @echo "Build finished. The HTML pages are in _build/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml + @echo + @echo "Build finished. The HTML pages are in _build/dirhtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in _build/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in _build/qthelp, like this:" + @echo "# qcollectiongenerator _build/qthelp/PyQtB.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile _build/qthelp/PyQtB.qhc" + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex + @echo + @echo "Build finished; the LaTeX files are in _build/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes + @echo + @echo "The overview file is in _build/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in _build/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in _build/doctest/output.txt." diff --git a/doc/_static/.gitignore b/doc/_static/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/doc/_templates/index.html b/doc/_templates/index.html new file mode 100644 index 000000000..f1a289077 --- /dev/null +++ b/doc/_templates/index.html @@ -0,0 +1,34 @@ +{% extends "layout.html" %} +{% set title = 'Overview' %} +{% block body %} +

{{ project }} {{ version }}

+ +

{{ project }} is a tool that eases the development of Python bindings for Qt-based libraries by + automating most of the process. It relies heavily on the ApiExtractor library to parse the + header files and manipulate the classes information while generating the code. This generated + code uses the + Boost::Python library + in order to bridge the C++ library and Python.

+ +

{{ project }} is based on the + QtScriptGenerator project.

+ +

Documentation

+ + + +
+ + + + + + +
+ +{% endblock %} diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html new file mode 100644 index 000000000..f15583b4d --- /dev/null +++ b/doc/_templates/layout.html @@ -0,0 +1,10 @@ +{% extends "!layout.html" %} +{% block rootrellink %} + +
  • {{ shorttitle }}{{ reldelim1 }}
  • +{% endblock %} +{% block extrahead %} + +{{ super() }} +{% endblock %} diff --git a/doc/compiling/cmake-primer.rst b/doc/compiling/cmake-primer.rst new file mode 100644 index 000000000..884cf15c1 --- /dev/null +++ b/doc/compiling/cmake-primer.rst @@ -0,0 +1,68 @@ + +.. _cmake-primer: + +************ +CMake primer +************ + +This chapter will is a basic introduction to CMake, the build system +used by PyQtB and the binding generator. + +The practical steps will be focusing in using cmake in a unix-like +(GNU/Linux) environment. + + +Configuring +=========== + +Project file - CMakeLists.txt +----------------------------- + +CMake parses the file CMakeLists.txt for information about the project, +like project name, dependencies, what should be compiled, what should be +shipped. + + +CMake variables +--------------- + +CMake can have its default behavior modified by providing some + +* ``CMAKE_INSTALL_PREFIX=`` sets the install prefix to + the specified path. +* ``CMAKE_MODULE_PATH=`` sets the extra directories + where CMake will try to find its modules. +* ``CMAKE_TOOLCHAIN_FILE=`` sets the path to the file that + describes the toolchain used to compile this project. Is is very useful + when using CMake with icecc to speedup compilation. + +You can define a variable using the ``-D`` switch. + +Invoking CMake +-------------- + +After writing the CMakeLists.txt and deciding which flags will be used, +you can invoke CMake using:: + + cmake + +For example, if you use the ``build/`` folder to build the project and +want it to be installed into ``/opt/sandbox/``, use the following lines:: + + cd build/ + cmake -DCMAKE_INSTALL_PREFIX=/opt/sandbox .. + +CMake will process the project file and write the output files in the +current directory + +Building +======== + +After the configuration process, the Makefiles are written and you can build +the project using :program:`make`. + +Installing +========== + +As in the building process, ``make install`` will install the files into +the target directory. diff --git a/doc/compiling/compiling.rst b/doc/compiling/compiling.rst new file mode 100644 index 000000000..638efa91a --- /dev/null +++ b/doc/compiling/compiling.rst @@ -0,0 +1,9 @@ +Compiling +********* + +.. toctree:: + :maxdepth: 3 + + cmake-primer + setup-apiextractor + setup-generator diff --git a/doc/compiling/setup-apiextractor.rst b/doc/compiling/setup-apiextractor.rst new file mode 100644 index 000000000..68c162f8b --- /dev/null +++ b/doc/compiling/setup-apiextractor.rst @@ -0,0 +1,56 @@ + +.. _api-extractor: + +************** +API Extractor +************** + +Overview +======== + +The **API Extractor** library is used by the binding generator to +parse the header and typesystem files to create an internal +representation of the API. It is based on the QtScriptGenerator +codebase. + +Getting the sources +=================== + +.. todo:: + Replace with the OSS project repo info + +* Git URL: https://dvcs.projects.maemo.org/git/python/apiextractor +* Web interface: https://dvcs.projects.maemo.org/git/?p=python/apiextractor + +To checkout the most updated version, use the following command:: + + $ git clone https://dvcs.projects.maemo.org/git/python/apiextractor/ + +Build requirements +================== + +* Qt4.5 development headers and libraries >= 4.5.0 +* libboost-graph >= 1.38.0 +* cmake >= 2.6.0 + +Building and installing +======================= + +To build and install just follow the generic cmake instructions in section +:ref:`cmake-primer`. + +Debian packaging +================ + +In order to compile this package in a debian environment, make sure the +following packages are installed: + +* debhelper (>= 5) +* cdbs +* cmake (>= 2.6.0) +* libboost-graph1.38-dev (>= 1.38.0) +* libqt4-dev (>= 4.5) + +And then you can build the package using:: + + $ dpkg-buildpackage -rfakeroot diff --git a/doc/compiling/setup-generator.rst b/doc/compiling/setup-generator.rst new file mode 100644 index 000000000..28fe2fbb3 --- /dev/null +++ b/doc/compiling/setup-generator.rst @@ -0,0 +1,54 @@ + +.. _python-bindings-generator: + +************************* +Python Bindings Generator +************************* + +Overview +========================================= + +The **Python Bindings Generator** (A.K.A. :program:`shiboken`) is +the program that creates the bindings source files from Qt headers and +auxiliary files (typesystems, ``global.h`` and glue files). It makes +heavy use of the :ref:`api-extractor` library. + + +Getting the sources +=================== + +* Git URL: https://dvcs.projects.maemo.org/git/python/shiboken +* Web interface: https://dvcs.projects.maemo.org/git/?p=python/shiboken + +To checkout the most updated version, use the following command:: + + $ git svn clone https://dvcs.projects.maemo.org/git/?p=python/shiboken + +Build requirements +================== + ++ CMake >= 2.6.0 ++ Qt4.5 libraries and development headers >= 4.5.0 ++ :ref:`api-extractor` + development headers + +Building and installing +======================= + +To build and install just follow the generic cmake instructions in +section :ref:`cmake-primer`. + +Debian packaging +================ + +In order to compile this package in a debian environment, make sure the +following packages are installed: + +* debhelper (>= 5) +* cdbs +* cmake (>= 2.6.0) +* libqt4-dev (>= 4.5) +* libapiextractor-dev (>= 0.1) + +And then you can build the package using:: + + $ dpkg-buildpackage -rfakeroot diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 000000000..6862c28d0 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +# +# PyQtB documentation build configuration file, created by +# sphinx-quickstart on Wed Apr 22 15:04:20 2009. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.append(os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 'sphinx.ext.refcounting', 'sphinx.ext.coverage'] + +rst_epilog = """ +.. |project| replace:: Shiboken +""" + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +source_encoding = 'utf-8' + +# The master toctree document. +#master_doc = 'contents' + +# General information about the project. +project = u'Shiboken' +copyright = u'2009, Nokia Corporation' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.1' +# The full version, including alpha/beta/rc tags. +release = '0.1' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = { +#} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = { '' : ''} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +html_additional_pages = { 'index' : 'index.html'} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +html_use_index = True + +# If true, the index is split into individual pages for each letter. +html_split_index = False + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +#htmlhelp_basename = 'PyQtBdoc' + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'PyQtB.tex', u'Brian Documentation', + u'Nokia Corporation', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True diff --git a/doc/contents.rst b/doc/contents.rst new file mode 100644 index 000000000..31d16dc9d --- /dev/null +++ b/doc/contents.rst @@ -0,0 +1,10 @@ +Table of contents +***************** +.. toctree:: + :numbered: + :maxdepth: 3 + + overview.rst + faq.rst + tutorial/introduction.rst + compiling/compiling.rst diff --git a/doc/dependency-pyqtb.svg b/doc/dependency-pyqtb.svg new file mode 100644 index 000000000..a458bf6fb --- /dev/null +++ b/doc/dependency-pyqtb.svg @@ -0,0 +1,600 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + API Extractor + 0.2 + Headers and libraries - compile-time + LGPL version 2.1 + + + + + + Shiboken (generator) + 0.1 + Binary executable - compile-time + GPL version 2 + + + + + + boost::graph + 1.38.0 + headers and libraries - compile-time + Boost Software License 1.0 + + + + + + + + + Boost + + + + Qt Software + + + + INdT/Nokia + + + + Python Foundation + + + + + + + + libshiboken + 0.1 + Headers and libraries - compile-time + LGPL version 2.1 + + + + + + Qt 4.5 + 4.5 + headers and libraries - compile-time and run-time + GNU General Public License v3 /GNU Lesser General Public Licence v2.1 + + + + + + Python + 2.6 + Headers and libraries - compile-time and run-time + Python license + + + + + + diff --git a/doc/faq.rst b/doc/faq.rst new file mode 100644 index 000000000..38cc3f186 --- /dev/null +++ b/doc/faq.rst @@ -0,0 +1,107 @@ +************************** +Frequently Asked Questions +************************** + +This is a list of Frequently Asked Questions about |project|. Feel free to +suggest new entries! + +General +======= + +What is the generator? +---------------------- + +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. + +What is the API Extractor? +-------------------------- + +It is a library that parses C++ header files and builds a data model around +them in order to ease the work of manipulating these data inside +*generators*. + + +Is there any similar tools around? +---------------------------------- + +The generator framework actually started as a fork of the qtscriptgenerator, +with the focus on python bindings instead of QtScript. After some time, the +python-specific code was split from the the header parsing and data model +code. The former became what we call *generator* while the latter is now +called *API Extractor*. + +What's the relationship between the generator and the API Extractor? +-------------------------------------------------------------------- + +The generator system relies heavily in the API Extractor classes, using +them as syntatic sugar to access the data model of the classes being +wrapped. + +What are the dependencies to run the generator? +----------------------------------------------- + +API Extractor, QtCore and QtXml. + +Creating bindings +================= + +Can I wrap non-Qt libraries? +---------------------------- + +Although it's not yet well tested, there's a good chance that non-Qt +libraries can be wrapped using the generator. But remember that +generator injects runtime dependency on Qt for the generated binding. + +Is there any runtime dependency on the generated binding? +--------------------------------------------------------- + +Yes. Only libshiboken, and the obvious Python interpreter +and the C++ library that is being wrapped. + +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. + +Is there any recommended build system? +-------------------------------------- + +Both API Extractor and generator uses and recommends the CMake build system. + +Can I write closed-source bindings with the generator? +------------------------------------------------------ + +Yes, as long as you use a LGPL version of Qt, due to runtime requirements. + +What is 'inject code'? +---------------------- + +That's how we call customized code that will be *injected* into the +generated at specific locations. They are specified inside the typesytem. + +How can I document my project? +------------------------------ + +The generator also can generate the API documentation based on the +C++ headers documentation using the qdoc syntax. Optionally you can +inject documentation at specific parts. Likewise *inject code*, the +customized documentation is specified inside the typesystem. + +Other +===== + +Is there any current limitation within the generator/API Extractor? +------------------------------------------------------------------- + +The generator currently does not automatically detects implicit C++ +type conversions. Also the code snippets in function signature and +examples are still in C++ inside the generated documentation. + diff --git a/doc/images/.directory b/doc/images/.directory new file mode 100644 index 000000000..e65475f65 --- /dev/null +++ b/doc/images/.directory @@ -0,0 +1,3 @@ +[Dolphin] +ShowPreview=true +Timestamp=2009,5,5,17,43,26 diff --git a/doc/images/bindinggen-development.png b/doc/images/bindinggen-development.png new file mode 100644 index 000000000..2dd64ba1d Binary files /dev/null and b/doc/images/bindinggen-development.png differ diff --git a/doc/images/boostgen.png b/doc/images/boostgen.png new file mode 100644 index 000000000..ae9d9fc3d Binary files /dev/null and b/doc/images/boostgen.png differ diff --git a/doc/images/boostqtarch.png b/doc/images/boostqtarch.png new file mode 100644 index 000000000..f1b145e9c Binary files /dev/null and b/doc/images/boostqtarch.png differ diff --git a/doc/overview.rst b/doc/overview.rst new file mode 100644 index 000000000..2ceb42fb8 --- /dev/null +++ b/doc/overview.rst @@ -0,0 +1,46 @@ +.. _gen-overview: + +****************** +Generator Overview +****************** + +In a few words, the Generator is a system that +parses a collecion of header and typesystem files, generating other +files (code, documentation, etc.) as result. + +Creating new bindings +===================== + +.. figure:: images/bindinggen-development.png + :scale: 80 + :align: center + + Creating new bindings + +Each module of the generator system has a specific role. + +1. Provide enough data about the classes and functions. +2. Generate valid code, with modifications from typesystems and + injected codes. +3. Modify the API to expose the objects in a Python-friendly way. +4. Insert customizations where handwritten code is needed. + +.. figure:: images/boostqtarch.png + :scale: 80 + :align: center + + Runtime architecture + +Handwritten inputs +================== + +Creating new bindings involves creating two pieces of "code": +The typesystem and the inject code. + +:typesystem: XML files that provides the developer with a tool to + customize the way that the generators will see the classes + and functions. For example, functions can be renamed, have + its signature changed and many other actions. +:inject code: allows the developer to insert handwritten code where + the generated code is not suitable or needs some customization. + diff --git a/doc/tutorial/bindinglibfoo.rst b/doc/tutorial/bindinglibfoo.rst new file mode 100644 index 000000000..fc256fbaa --- /dev/null +++ b/doc/tutorial/bindinglibfoo.rst @@ -0,0 +1,76 @@ +.. highlight:: xml + +.. _gentut-bindinglibfoo: + +Binding libfoo with the Generator +================================= + +In order to create bindings for a library based on Qt4 a number of components +must be available in 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 **boostgenerator**. + + Typesystems for the Qt4 Python bindings. + + Headers for the library to be bound. + +With the above listed in place 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/PyQtB/typesystem**, the exact location +can be checked with pkg-config: + +:: + + $ pkg-config qt4python --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: + +:: + + + + +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..bc60fe284 --- /dev/null +++ b/doc/tutorial/buildingthebinding.rst @@ -0,0 +1,133 @@ +.. _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: + +:: + + $ boostgenerator 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 **qt4python** and a +simple ``pkg-config qt4python --cflags --libs`` will retrieve the information +needed to build the new binding. + +The Qt4 bindings file ``qt4python.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/qt45``, remember to export it to the ``PKG_CONFIG_PATH`` +environment variable. +For example: ``export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/opt/qt45/lib/pkgconfig`` + +There is a vital information also available through pkg-config: +the **typesystemdir** variable. It is used like this: +``pkg-config qt4python --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** +:: + + LIBTEST_DIR = ../../libfoo + LIBS = -lboost_python-gcc43-1_38-py25 -lpython2.5 \ + `pkg-config qt4python --libs` \ + -lfoo -L$(LIBTEST_DIR) \ + -lpthread -ldl -lutil + CFLAGS = -I/usr/share/qt4/mkspecs/linux-g++ -I. \ + -I$(LIBTEST_DIR) \ + `pkg-config qt4python --cflags` \ + -I/usr/include/python2.5\ + -I/usr/include/boost/python + QT4TYPESYSTEM_DIR = `pkg-config --variable=typesystemdir qt4python` + QT4HEADER_DIRS = `pkg-config --variable=includedir QtCore`:`pkg-config --variable=includedir QtCore`/.. + + SOURCES = math_wrapper.cpp foo_module_wrapper.cpp foo_global_functions_wrapper.cpp + OBJECTS = math_wrapper.o foo_module_wrapper.o foo_global_functions_wrapper.o + + all: generate compile link + + generate: + boostgenerator ../data/global.h \ + --include-paths=$(LIBTEST_DIR):$(QT4HEADER_DIRS):/usr/include \ + --typesystem-paths=../data:$(QT4TYPESYSTEM_DIR) \ + --output-directory=.. \ + ../data/typesystem_foo.xml + + compile: $(SOURCES) + g++ -fPIC -DPIC $(CFLAGS) math_wrapper.cpp -c + g++ -fPIC -DPIC $(CFLAGS) foo_global_functions_wrapper.cpp -c + g++ -fPIC -DPIC $(CFLAGS) foo_module_wrapper.cpp -c + + link: + g++ -shared -Wl,-soname,foo.so -o foo.so $(LIBS) $(OBJECTS) + + test: + LD_LIBRARY_PATH=$(LIBTEST_DIR) python -c \ + "import foo; print dir(foo); m = foo.Math(); print m.squared(5)" + + clean: + rm -rf *.o *.so *.?pp *.log + + +Keepe 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. + +**Warning:** + The order in which the link flags are passed matters. + **libboost_python** must come first, otherwise weeping + and gnashing of teeth will follow. + +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..d1ac2392e --- /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. + +The 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 + diff --git a/doc/tutorial/images/generatorworkings.png b/doc/tutorial/images/generatorworkings.png new file mode 100644 index 000000000..d35a565ff Binary files /dev/null and b/doc/tutorial/images/generatorworkings.png differ 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + bindingsource code + + + + + + + typesystemdescriptions + + + + customsourcecode + + + + + + libraryheaders + + + + + + Parser + + + + GeneratorBackend + + + + TypeDatabase + + + + + diff --git a/doc/tutorial/introduction.rst b/doc/tutorial/introduction.rst new file mode 100644 index 000000000..5234551b7 --- /dev/null +++ b/doc/tutorial/introduction.rst @@ -0,0 +1,31 @@ +Binding Generation Tutorial +*************************** + +This tutorial intends to describe the process of binding creation with +|project| 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 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 +being able to be imported and used from a Python program. + +**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..217577a4f --- /dev/null +++ b/doc/tutorial/libfoo.rst @@ -0,0 +1,68 @@ +.. highlight:: cpp + +.. _gentut-libfoo: + +Creating the foo library +========================= + +In this section is the code and build instructions for a very simple Qt4 based +library which will serve as a 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 Trolltech's **qmake**. + +Put the files below in a directory called **libfoo**. Be aware that this +directory will be refered 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 + + 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..f36a8769a --- /dev/null +++ b/doc/tutorial/typesystemcreation.rst @@ -0,0 +1,136 @@ +.. highlight:: xml + +.. _gentut-typesystem: + +Creating the Typesystem Description +=================================== + +The type system is a 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, alterations +to classes and function signatures to better suit the target language, +and listing the components that should be rejected for the binding. + +**PyQtB** uses a typesystem format similar to the ones used **QtJambi** and +**QtScript**, thoroughly described in the page *"The Qt Jambi Type System"*. [#]_ + +The divergences between **PyQtB** 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_test.xml** +:: + + + + + + + + +The inclusion of the other typesystem files is achieved with the +``load-typesystem`` tag. The ``generate`` attribute must be set to ``"no"`` +or else 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 types known. 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 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: + +:: + + + +And is used as in this example: + +:: + + + + + + +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``: + +:: + + + + +Unused Tags +~~~~~~~~~~~ + +Some tags defined in the QtScript/QtJambi typesystem has no effect in **PyQtB** +typesystem, they are: + + + conversion-rule + + argument-map + +Changes to ``"inject-code"`` Tag +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can pass a file name to the **inject-code** tag, 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 **BoostGenerator** 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. + +:: + + + + +.. [#] 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 -- cgit v1.2.3