Commit db2d56db authored by Manuel Günther's avatar Manuel Günther

Updated documentation and wrote tutorial-style docs for extension usage.

parent 5998896f
......@@ -19,198 +19,15 @@
Python/C++ Bob Extension Building Support
===========================================
This package provides a simple mechanims for building Python/C++ extensions for
`Bob <http://www.idiap.ch/software/bob/>`_. You use this package by including
it in your ``setup.py`` file.
Building with ``zc.buildout`` is possible using the ``develop`` recipe in
`bob.buildout <http://pypi.python.org/pypi/bob.buildout>`_. Follow the
instructions described on that package for this recipe.
This package is part of the signal-processing and machine learning toolbox Bob_.
It provides a simple mechanism for using Bob_, or extending Bob_ by building packages using either a pure Python API, or even a mix of C++ and python.
Further documentation on this package can be found `here <https://www.idiap.ch/software/bob/docs/latest/bioidiap/bob.extension/master/index.html>`_.
Preparing for C++ Compilation
-----------------------------
Creating C++/Python bindings should be trivial. Firstly, edit your ``setup.py``
so that you include the following::
from setuptools import dist
dist.Distribution(dict(setup_requires=['bob.extension']))
from bob.extension import Extension, Library, build_ext
...
setup(
name="bob.myext",
version="1.0.0",
...
setup_requires=[
'bob.extension',
],
...
ext_modules=[
Extension("bob.myext._myext",
[
"bob/myext/ext/file1.cpp",
"bob/myext/ext/file2.cpp",
"bob/myext/ext/main.cpp",
],
packages = [ #pkg-config modules to append
'blitz>=0.10',
],
bob_packages = [ #optionally, bob C++ modules to import
"bob.core"
],
include_dirs = [ #optionally, include directories
"bob/myext/ext/headers/",
],
),
... #add more extensions if you wish
],
cmdclass = {
'build_ext': build_ext
},
...
)
These modifications will allow you to compile extensions that are linked
against the named ``pkg-config`` modules. Other modules and options can be set
manually using `the standard options for python extensions
<http://docs.python.org/2/extending/building.html>`_.
Adding pure C++ libraries
-------------------------
Most of the bob packages will include pure C++ code that can be used in other packages.
When your package should export a library with pure C++ code as well, you can build it with the ``Library`` extension.
You can simply add this ``Library`` to the list of ``ext_modules`` as follows::
setup(
...
ext_modules=[
Library("bob_myext",
[
"bob/myext/ext/cpp/cppfile1.cpp",
"bob/myext/ext/cpp/cppfile2.cpp",
],
package_directory = os.path.dirname(os.path.realpath(__file__)),
target_directory = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'bob', 'myext'),
version = "1.0.0",
bob_packages = [...],
packages = [...],
...
),
Extension("bob.my_ext._myext",
...
libraries = ["bob_myext",...]
)
],
cmdclass = {
'build_ext': build_ext
},
...
)
This will compile the given source files of the library using `CMake <http://www.cmake.org>`_.
Please assure that the name of the library ``bob_myext`` is compatible with your package name so that the library can be imported in other packages using the ``bob_packages`` list.
Also, it is assumed that **all** header files that are exported by the C++ library are listed in the *bob/myext/include* directory.
This directory is automatically added to the list of include directories -- in your own package and in all other packages that use the ``bob_packages`` list.
Compiling the module
--------------------
To hook-in the building on the package through ``zc.buildout``, add the following section to your ``buildout.cfg``::
[bob.myext]
recipe = bob.buildout:develop
verbose = true ;enables command-line verbosity
debug = true ;compiles the module in debug mode
If you need to build multiple eggs, you will need **one entry per project** on
your ``buildout.cfg``. This includes, possibly, dependent projects. Currently,
``zc.buildout`` ignores the ``setup_requires`` entry on your ``setup.py`` file.
The recipe above creates a new interpreter that hooks that package in and
builds the project considering variables like ``prefixes`` into consideration.
By default, the extension code is compiled into a local directory called ``build``.
This directory, after compilation, can be removed without issues, the resulting libraries will be copied into the package directories.
To change the build directory of your package, and all other bob packages, you can define the ``BOB_BUILD_DIRECTORY`` environment variable, e.g.,::
$ python bootstrap.py
$ BOB_BUILD_DIRECTORY=/tmp/bob_build_dir ./bin/buildout
Again, after successful compilation, this directory can be removed safely.
Python API to pkg-config and Boost
----------------------------------
This package alson contains a set of Pythonic bindings to the popular
pkg-config configuration utility. It allows distutils-based setup files to
query for libraries installed on the current system through that command line
utility. library.
Using the ``pkgconfig`` class
=============================
To use this package at your ``setup.py`` file, you will need to let distutils
know it needs it before importing it. You can achieve this with the following
trick::
from setuptools import dist
dist.Distribution(dict(setup_requires='bob.extension'))
from bob.extension.pkgconfig import pkgconfig
.. note::
In this case, distutils should automatically download and install this
package on the environment it is required to setup other package.
After inclusion, you can just instantiate an object of type ``pkgconfig``::
>>> zlib = pkgconfig('zlib')
>>> zlib.version # doctest: SKIP
1.2.8
>>> zlib.include_directories() # doctest: SKIP
['/usr/include']
>>> zlib.library_dirs # doctest: SKIP
['/usr/lib']
>>> zlib > '1.2.6'
True
>>> zlib > '1.2.10'
False
Using the ``boost`` class
=========================
To use this package at your ``setup.py`` file, you will also need the same
trick as with ``pkgconfig``::
from setuptools import dist
dist.Distribution(dict(setup_requires='bob.extension'))
from bob.extension.boost import boost
After inclusion, you can just instantiate an object of type ``boost``::
>>> boost_pkg = boost('>= 1.47')
>>> boost.version # doctest: SKIP
1.50.0
>>> boost.include_directory # doctest: SKIP
'/usr/include'
>>> libpaths, libnames = boost.libconfig(['system', 'python'])
>>> print(libpaths) # doctest: SKIP
['/usr/lib']
>>> print(libnames) # doctest: SKIP
['boost_system-mt', 'boost_python-mt-py27']
Installation
------------
To install this package -- alone or together with other `Packages of Bob <https://github.com/idiap/bob/wiki/Packages>`_ -- please read the `Installation Instructions <https://github.com/idiap/bob/wiki/Installation>`_.
For Bob_ to be able to work properly, some dependent packages mus be installed.
Please make sure that you have read the `Dependencies <https://github.com/idiap/bob/wiki/Dependencies>`_ for your operating system.
.. _bob: https://www.idiap.ch/software/bob
.. vim: set fileencoding=utf-8 :
.. Manuel Guenther <manuel.guenther@idiap.ch>
.. Fri Oct 10 14:03:53 CEST 2014
..
.. Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
======================================
C++ API of the Documentation classes
======================================
This section includes information for using the pure C++ API for the documentation classes, which can be accessed after including:
.. code-block:: c++
# include <bob.extension/documentation.h>
The classes, which are described in more detail below, can be used to format the documentation of your C/C++ functions that are bound to Python.
Any free text that you specify to describe your functions will be interpreted as `reStructuredText <http://docutils.sourceforge.net/rst.html>`_.
Hence, it is possible to use any directives like ``.. note::``, ``.. math::``, and even links inside the documentation like ``:py:class:`` and references as ``[REF]_``.
Function Documentation
----------------------
.. cpp:class:: bob::extension::FunctionDoc
To document a function (either a stand-alone function or a member function of a class), you should use the :cpp:class:`bob::extension::FunctionDoc`.
.. cpp:function:: FunctionDoc(\
const char* const function_name,\
const char* const short_desctiption,\
const char* const long_description = NULL,\
bool is_member_function = false\
)
In the constructor, you specify the function name and a short description.
If wanted, you can define a longer description as well.
When you use this FunctionDoc to document a member function of a class, please set ``is_member_function = true``.
.. cpp:function:: FunctionDoc& add_prototype(\
const char* const variables,\
const char* const return_value = "None"\
)
Adds a prototype of the documented function declaration to the function.
All ``variables`` and all ``return_value``'s listed must be documented using the :cpp:func:`add_parameter` or :cpp:func:`add_return` functions.
Only the default return value ``None`` does not need documentation.
``variables`` is a single string containing a comma-separated list of parameter names.
Use ``..., [name]`` to indicate that name is ``name`` is an optional parameter.
``return_value`` is a single string containing a comma-separated list of return value names.
If a single name is given, only a single value is returned, otherwise a tuple will be returned by your function.
.. note::
Each :cpp:class:`FunctionDoc` needs at least one prototype.
In opposition to pure Python functions, specifying multiple prototypes is allowed here as well.
.. cpp:function:: FunctionDoc& add_parameter(\
const char* const parameter_name,\
const char* const parameter_type,\
const char* const parameter_description\
)
Adds a description for a given parameter.
``parameter_name`` must be one of the names listed in the ``variables`` of the :cpp:func:`add_prototype` function.
``parameter_type`` specifies the expected type of this parameter.
You can use any free text to describe the type.
When ``:py:class:`` directives or similar are used, they will be interpreted correctly.
``parameter_description`` includes free text to describe, what the parameter is used for.
.. cpp:function:: FunctionDoc& add_return(\
const char* const return_name,\
const char* const return_type,\
const char* const return_description\
)
Adds a description for a given return value.
``return_name`` must be one of the names listed as a ``return_value`` of the :cpp:func:`add_prototype` function.
``return_type`` specifies the type of this return value.
You can use any free text to describe the type.
When ``:py:class:`` directives or similar are used, they will be interpreted correctly.
``return_description`` includes free text to describe, what the return value contains.
.. cpp:function:: const char* const name() const
Returns the name of the function defined in the constructor.
.. cpp:function:: const char* const doc(const unsigned alignment = 72, const unsigned indent = 0) const
Generates and returns the documentation string.
The free text in the documentation is aligned to ``alignment`` characters, by default 72, so that it can be viewed correctly inside of an 80-character Python console.
The ``indent`` is an internal parameter and should not be changed.
.. cpp:function:: void print_usage() const
Prints a function usage string to console, including all information specified by the member functions above.
All functions adding information to the :cpp:class:`bob::extension::FunctionDoc` return a reference to the current object, so that you can use it inline, like:
.. code-block:: c++
auto function_doc = bob::extension::FunctionDoc(
"function_name",
"Short description of the function",
"Long description of the function using reStructuredText including directives like :py:class:`bob.blitz.array`."
)
.add_prototype("param1, [param2]", "ret")
.add_parameter("param1", "int", "An int value used for ...")
.add_parameter("param2", "float", "[Default: ``0.5``] A float value describing ...")
.add_return("ret", ":py:class:`bob.blitz.array`", "An array ...")
;
During the binding of your function, you can use it, like:
.. code-block:: c++
static PyMethodDef module_methods[] = {
...
{
function_doc.name(),
(PyCFunction)function,
METH_VARARGS|METH_KEYWORDS,
function_doc.doc()
},
...
};
Variables Documentation
-----------------------
.. cpp:class:: bob::extension::VariableDoc
To document a variable (either a stand-alone function or a member function of a class), you should use the :cpp:class:`bob::extension::VariableDoc`.
.. cpp:function:: VariableDoc(\
const char* const variable_name,\
const char* const variable_type,\
const char* const short_desctiption,\
const char* const long_description = NULL\
)
In the constructor, you specify the variable name, its type and a short description.
The structure is identical to the :cpp:func:`FunctionDoc::add_parameter` function.
If wanted, you can define a longer description as well.
.. cpp:function:: char* name() const
Returns the name of the variable defined in the constructor.
.. cpp:function:: char* doc(const unsigned alignment = 72) const
Generates and returns the documentation string, which is composed of the information provided in the constructor.
The free text in the documentation is aligned to ``alignment`` characters, by default 72, so that it can be viewed correctly inside of an 80-character Python console.
Class Documentation
-------------------
.. cpp:class:: bob::extension::ClassDoc
To document a function (either a stand-alone function or a member function of a class), you should use the :cpp:class:`bob::extension::FunctionDoc`.
.. cpp:function:: ClassDoc(\
const char* const class_name,\
const char* const short_desctiption,\
const char* const long_description = NULL\
)
In the constructor, you specify the class name and a short description.
If wanted, you can define a longer description as well.
.. cpp:function:: ClassDoc& add_constructor(\
const FunctionDoc& constructor_doc\
)
Adds the documentation of the constructor, which itself is a :cpp:class:`FunctionDoc`.
.. note::
You should specify the return value of your constructor to be ``""`` to overwrite the default value ``"None"``.
.. note::
A class can have only a single constructor documentation.
Hence, this function can be called only once for each class.
.. cpp:function:: char* name() const
Returns the name of the class defined in the constructor.
.. cpp:function:: char* doc(const unsigned alignment = 72) const
Generates and returns the documentation string, which is composed of the information provided in the constructor, and the constructor documentation.
The free text in the documentation is aligned to ``alignment`` characters, by default 72, so that it can be viewed correctly inside of an 80-character Python console.
.. cpp:function:: void print_usage() const
Prints the usage of the constructor.
See :cpp:func:`FunctionDoc::print_usage` for details.
As for functions, the :cpp:class:`bob::extension::ClassDoc` is designed to be used inline, like:
.. code-block:: c++
auto class_doc = bob::extension::ClassDoc(
"class_name",
"Short description of the class",
"Long description of the class using reStructuredText including directives like :py:class:`bob.blitz.array`."
)
.add_constructor(
bob::extension::FunctionDoc(
"class_name",
"Short description of the constructor",
"Long description of the constructor"
true
)
.add_prototype("param1, [param2]", "")
.add_parameter("param1", "int", "An int value used for ...")
.add_parameter("param2", "float", "[Default: ``0.5``] A float value describing ...")
);
This diff is collapsed.
......@@ -20,6 +20,7 @@ Documentation
:maxdepth: 2
guide
cpp_api
py_api
Indices and tables
......
......@@ -5,6 +5,7 @@
.. Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
.. _bob's website: https://www.idiap.ch/software/bob
.. _bob: https://www.idiap.ch/software/bob
.. _c++: http://www2.research.att.com/~bs/C++.html
.. _distutils: http://docs.python.org/distutils/
.. _git: http://git-scm.com/
......
......@@ -11,7 +11,7 @@ from setuptools import setup, find_packages
setup(
name="bob.extension",
version="0.3.0a0",
version="2.0.0a0",
description="Helps projects building Python/C++ extensions for Bob",
url='http://github.com/bioidiap/bob.extension',
license="BSD",
......@@ -32,6 +32,7 @@ setup(
],
classifiers = [
'Framework :: Bob',
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment