diff --git a/.bzrignore b/.bzrignore index c05dce2..1208379 100644 --- a/.bzrignore +++ b/.bzrignore @@ -5,4 +5,7 @@ ./pybindgen/version.py ./doc/_build ./.waf-* +./doc/figures/work-flow-basic.png +./doc/figures/work-flow-gccxml-apidefs.png +./doc/figures/work-flow-gccxml.png diff --git a/doc/Makefile b/doc/Makefile index 387918c..ab25083 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -30,11 +30,13 @@ clean: -rm -rf _build/* html: + cd figures && $(MAKE) $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html @echo @echo "Build finished. The HTML pages are in _build/html." dirhtml: + cd figures && $(MAKE) $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml @echo @echo "Build finished. The HTML pages are in _build/dirhtml." @@ -65,6 +67,7 @@ qthelp: @echo "# assistant -collectionFile _build/qthelp/PyBindGen.qhc" latex: + cd figures && $(MAKE) $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex @echo @echo "Build finished; the LaTeX files are in _build/latex." diff --git a/doc/apiref.rst b/doc/apiref.rst new file mode 100644 index 0000000..d8dfa5e --- /dev/null +++ b/doc/apiref.rst @@ -0,0 +1,33 @@ + +PyBindGen API Reference +======================= + + +Higher layers +----------------------- + +.. toctree:: + :maxdepth: 2 + + module + function + enum + cppclass + cppmethod + cppattribute + cppexception + container + + gccxmlparser + settings + + +Lower layers +----------------------- +.. toctree:: + :maxdepth: 2 + + utils + typehandlers + cppclass_typehandlers + codesink diff --git a/doc/codesink.rst b/doc/codesink.rst new file mode 100644 index 0000000..4ce4f7f --- /dev/null +++ b/doc/codesink.rst @@ -0,0 +1,10 @@ + +================================================================= +typehandlers.codesink: classes that receive generated source code +================================================================= + + +.. automodule:: pybindgen.typehandlers.codesink + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/conf.py b/doc/conf.py index f4015cc..02c31f1 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -150,7 +150,7 @@ html_static_path = ['_static'] #html_split_index = False # If true, links to the reST sources are added to the pages. -html_show_sourcelink = False +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 diff --git a/doc/container.rst b/doc/container.rst new file mode 100644 index 0000000..ccf899f --- /dev/null +++ b/doc/container.rst @@ -0,0 +1,10 @@ + +========================================================== +container: wrap STL containers +========================================================== + + +.. automodule:: pybindgen.container + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/cppattribute.rst b/doc/cppattribute.rst new file mode 100644 index 0000000..9725725 --- /dev/null +++ b/doc/cppattribute.rst @@ -0,0 +1,10 @@ + +============================================== +cppattribute: wrap class/instance attributes +============================================== + + +.. automodule:: pybindgen.cppattribute + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/cppclass.rst b/doc/cppclass.rst index a0055b9..4508f19 100644 --- a/doc/cppclass.rst +++ b/doc/cppclass.rst @@ -1,6 +1,6 @@ ======================= -cppclass +cppclass: wrap C++ classes or C structures ======================= diff --git a/doc/cppclass_typehandlers.rst b/doc/cppclass_typehandlers.rst new file mode 100644 index 0000000..11249f0 --- /dev/null +++ b/doc/cppclass_typehandlers.rst @@ -0,0 +1,10 @@ + +======================= +cppclass_typehandlers: type handlers for C++ classes (or C structures) +======================= + + +.. automodule:: pybindgen.cppclass_typehandlers + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/cppexception.rst b/doc/cppexception.rst new file mode 100644 index 0000000..c11a15b --- /dev/null +++ b/doc/cppexception.rst @@ -0,0 +1,10 @@ + +============================================== +cppexceptions: translate C++ exceptions into Python +============================================== + + +.. automodule:: pybindgen.cppexception + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/cppmethod.rst b/doc/cppmethod.rst index 941f23d..b05b861 100644 --- a/doc/cppmethod.rst +++ b/doc/cppmethod.rst @@ -1,7 +1,7 @@ -============================== -cppmethod: C++ method wrappers -============================== +============================================== +cppmethod: wrap class methods and constructors +============================================== .. automodule:: pybindgen.cppmethod diff --git a/doc/enum.rst b/doc/enum.rst new file mode 100644 index 0000000..af89494 --- /dev/null +++ b/doc/enum.rst @@ -0,0 +1,10 @@ + +========================================================== +enum: wrap enumrations +========================================================== + + +.. automodule:: pybindgen.enum + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/figures/Makefile b/doc/figures/Makefile new file mode 100644 index 0000000..91652a0 --- /dev/null +++ b/doc/figures/Makefile @@ -0,0 +1,13 @@ + +figures_dia=$(shell echo *.dia) +figures_png=$(figures_dia:.dia=.png) + + +all: $(figures_png) + +%.png: %.dia + dia $< -e $@ + + +clean: + -rm -f $(figures_png) diff --git a/doc/figures/work-flow-basic.dia b/doc/figures/work-flow-basic.dia new file mode 100644 index 0000000..ac1f16f Binary files /dev/null and b/doc/figures/work-flow-basic.dia differ diff --git a/doc/figures/work-flow-gccxml-apidefs.dia b/doc/figures/work-flow-gccxml-apidefs.dia new file mode 100644 index 0000000..5fb3bcc Binary files /dev/null and b/doc/figures/work-flow-gccxml-apidefs.dia differ diff --git a/doc/figures/work-flow-gccxml.dia b/doc/figures/work-flow-gccxml.dia new file mode 100644 index 0000000..124a6d0 Binary files /dev/null and b/doc/figures/work-flow-gccxml.dia differ diff --git a/doc/gccxmlparser.rst b/doc/gccxmlparser.rst index be4d376..c7488df 100644 --- a/doc/gccxmlparser.rst +++ b/doc/gccxmlparser.rst @@ -1,16 +1,8 @@ -======================= -gccxmlparser -======================= +========================================================== +gccxmlparser: scan header files to extract API definitions +========================================================== --------- -Overview --------- - -This module uses (py)gccxml to scan header files and extract definitions. - -gccxmlparser ---------------- .. automodule:: pybindgen.gccxmlparser :members: diff --git a/doc/index.rst b/doc/index.rst index 23c2c7a..3e20848 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,17 +9,10 @@ Welcome to PyBindGen's documentation! Contents: .. toctree:: - :maxdepth: 2 + :maxdepth: 3 tutorial - - module - utils - function - cppclass - cppmethod - - gccxmlparser + apiref Indices and tables diff --git a/doc/module.rst b/doc/module.rst index 8d52ff0..c6043c2 100644 --- a/doc/module.rst +++ b/doc/module.rst @@ -1,7 +1,7 @@ -======================= -module -======================= +============================================================== +module: generate Python modules and submodules +============================================================== .. automodule:: pybindgen.module diff --git a/doc/settings.rst b/doc/settings.rst new file mode 100644 index 0000000..8ac3abe --- /dev/null +++ b/doc/settings.rst @@ -0,0 +1,10 @@ + +============================================== +settings: pybindgen global settings +============================================== + + +.. automodule:: pybindgen.settings + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 12f2a3f..81219b4 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -1,28 +1,28 @@ ======================= -tutorial +PyBindGen Tutorial ======================= -What is pybindgen ? +What is PyBindGen ? =================== -Pybindgen is a tool which can be used to generate python bindings +PyBindGen is a tool which can be used to generate python bindings for C or C++ APIs. It is similar in scope to tools such as boost::python, SWIG, and a few others but has a number of specific features which make it especially useful in a number of cases: - - pybindgen is implemented in python and is used and controlled + - PyBindGen is implemented in python and is used and controlled through python; - - pybindgen error messages do not involve c++ template deciphering + - PyBindGen error messages do not involve c++ template deciphering (as in boost::python); - - pybindgen generates highly-readable C or C++ code so it is + - PyBindGen generates highly-readable C or C++ code so it is possible to step into and debug the bindings; - - In simple cases, pybindgen is really easy to use. In more + - In simple cases, PyBindGen is really easy to use. In more complicated cases, it does offer all the flexibility you need to wrap complex C or C++ APIs; - - pybindgen also provides an optional tool to parse C and C++ + - PyBindGen also provides an optional tool to parse C and C++ headers and generate automatically bindings for them, potentially using extra inline or out-of-line annotations. This tool is based on gccxml and pygccxml: it can be used to generate the first @@ -33,9 +33,34 @@ it especially useful in a number of cases: This tutorial will show how to build bindings for a couple of common C and C++ API idioms and, then, will proceed to show how to use the automatic binding generator. + +Work flows +========== + +PyBindGen is only a Python module. The programmer must write a Python +script that uses the module in order to generate the bindings. There +are several ways that PyBindGen can be used: + + 1. Basic mode, script that directly generates the bindings; + + .. image:: figures/work-flow-basic.* + + 2. Automatically scan header files and generate the bindings + directly (see :ref:`Header file scanning with (py)gccxml`); + + .. image:: figures/work-flow-gccxml.* + + 3. Automatically scan header files to generate API defs file, that + file can later be used to generate the bindings. See (see + :ref:`Header file scanning with (py)gccxml: python intermediate + file`); + + .. image:: figures/work-flow-gccxml-apidefs.* + + A simple example ================ -The best way to get a feel for what pybindgen looks like is to go through a +The best way to get a feel for what PyBindGen looks like is to go through a simple example. Let's assume that we have a simple C API as shown below declared in a header my-module.h: @@ -132,7 +157,6 @@ should be self-explanatory:: Wrapping types by value ======================= ---------------- Primitive types --------------- @@ -219,7 +243,6 @@ With the resulting python-visible API:: >>> MyModule.MyModuleDoAction (MyModule.CONSTANT_B) MyModuleDoAction: 1 --------------- Compound types -------------- @@ -259,8 +282,8 @@ from python:: struct.add_instance_attribute('b', 'int') The name of the method called here, 'add_instance_attribute' reflects the fact that -pybindgen can wrap both C and C++ APIs: in C++, there exist both instance and static -members so, pybindgen provides two methods: add_instance_attribute and add_static_attribute +PyBindGen can wrap both C and C++ APIs: in C++, there exist both instance and static +members so, PyBindGen provides two methods: add_instance_attribute and add_static_attribute to register these two kinds of members. Our C API then becomes accessible from python:: @@ -282,7 +305,6 @@ Our C API then becomes accessible from python:: -20 ------------ C++ classes ----------- @@ -384,7 +406,6 @@ The resulting python API reflects the underlying C++ API very closely:: >>> inner.Do(MyModule.Outer.INNER_A) --------------- C++ namespaces -------------- @@ -441,11 +462,10 @@ only by value but, a large fraction of real-world APIs use raw pointers (and, in the case of C++, smart pointers) as arguments or return values of functions/methods. -Rather than try to explain the detail of every option offered by pybindgen +Rather than try to explain the detail of every option offered by PyBindGen to deal with pointers, we will go through a couple of very classic memory management schemes and examples. ------------------------- Function returns pointer ------------------------ @@ -466,7 +486,7 @@ can write:: mod.add_function('DoSomethingAndReturnClass', retval('MyClass *', caller_owns_return=True), []) -The above will tell pybindgen that the caller (the python runtime) becomes +The above will tell PyBindGen that the caller (the python runtime) becomes responsible for deleting the instance of MyClass returned by the function DoSomethingAndReturnClass when it is done with it. @@ -539,7 +559,7 @@ To wrap this class, we first need to declare our class:: decref_method='Unref', peekref_method='PeekRef')) -The above allows pybindgen to maintain and track the reference count +The above allows PyBindGen to maintain and track the reference count of the MyClass object while the code below shows how we can declare a function taking a pointer as input:: @@ -569,12 +589,12 @@ While classic reference counting rules require that the callee returns a reference to the caller (i.e., it calls Ref on behalf of the caller before returning the pointer), some APIs will undoubtedly return a pointer and expect the caller to acquire a reference to the returned object by -calling Ref himself. Pybindgen hopefully can be made to support this +calling Ref himself. PyBindGen hopefully can be made to support this case too:: mod.add_function('DoSomething', retval('MyClass *', caller_owns_return=False), []) -Which instructs pybindgen that DoSomething is not to be trusted and that it should +Which instructs PyBindGen that DoSomething is not to be trusted and that it should acquire ownership of the returned pointer if it needs to keep track of it. @@ -582,7 +602,7 @@ A STL container --------------- If you have a function that takes a STL container, you have to -tell pybindgen to wrap the container first: +tell PyBindGen to wrap the container first: .. code-block:: c++ @@ -602,9 +622,12 @@ Is wrapped by:: .. ============================================== +Advanced usage +============== + Basic interface with error handling -=================================== +----------------------------------- It is also possible to declare a error handler. The error handler will be invoked for API definitions that cannot be wrapped for some @@ -658,7 +681,8 @@ Module.add_function() do that in a way that the error handler can be invoked and the function is simply not wrapped if the error handler says so. ------------------------------------- +.. _header-file-scanning: + Header file scanning with (py)gccxml ------------------------------------ @@ -688,7 +712,8 @@ The above script will generate the bindings for the module directly. It expects the input header file, a.h, as first command line argument. --------------------------------------------------------------- +.. _header-file-scanning-apidefs: + Header file scanning with (py)gccxml: python intermediate file -------------------------------------------------------------- diff --git a/doc/typehandlers.rst b/doc/typehandlers.rst new file mode 100644 index 0000000..2b875e5 --- /dev/null +++ b/doc/typehandlers.rst @@ -0,0 +1,10 @@ + +======================= +typehandlers.base: abstract base classes for type handlers and wrapper generators +======================= + + +.. automodule:: pybindgen.typehandlers.base + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/utils.rst b/doc/utils.rst index 7506b8e..8bf11be 100644 --- a/doc/utils.rst +++ b/doc/utils.rst @@ -1,6 +1,6 @@ ======================= -utils +utils: internal utilities =======================