From 1de85e09fc49caa18d29b66899f609624501bdc7 Mon Sep 17 00:00:00 2001 From: Manuel Gunther <siebenkopf@googlemail.com> Date: Thu, 3 Mar 2016 11:33:23 -0700 Subject: [PATCH] C++ exception handling is now disabled in debug mode (when using the BOB_TRY and BOB_CATCH_... macros), see #8 --- bob/extension/include/bob.extension/defines.h | 11 ++++++++++- doc/cpp_api.rst | 16 ++++++++++++---- doc/extension.rst | 10 ++++++++-- doc/guide.rst | 4 ++-- version.txt | 2 +- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/bob/extension/include/bob.extension/defines.h b/bob/extension/include/bob.extension/defines.h index 7183431..f8ae04e 100644 --- a/bob/extension/include/bob.extension/defines.h +++ b/bob/extension/include/bob.extension/defines.h @@ -32,10 +32,18 @@ #define PyBob_NumberCheck(x) (PyInt_Check(x) || PyLong_Check(x) || PyFloat_Check(x) || PyComplex_Check(x)) + +#ifdef BOB_DEBUG + +#define BOB_TRY { +#define BOB_CATCH_MEMBER(m,r) } +#define BOB_CATCH_FUNCTION(m,r) } + +#else // BOB_DEBUG + // BOB_TRY is simply a try{ #define BOB_TRY try{ - // for catching exceptions, you can define a message, and you have to select the error return value (i.e., -1 for constructors, and 0 for other functions) // There exist two macros that will print slightly different messages. @@ -61,5 +69,6 @@ return ret;\ } +#endif // BOB_DEBUG #endif // BOB_EXTENSION_DEFINES_H_INCLUDED diff --git a/doc/cpp_api.rst b/doc/cpp_api.rst index 2892e3a..534b836 100644 --- a/doc/cpp_api.rst +++ b/doc/cpp_api.rst @@ -11,7 +11,7 @@ ================== In the header file ``<bob.extension/defines.h>`` we have added some functions that help you to keep your code short and clean. -Particularly, we provide three preprocessor definitions: +Particularly, we provide three preprocessor directives: .. c:macro:: BOB_TRY @@ -19,19 +19,27 @@ Particularly, we provide three preprocessor definitions: .. c:macro:: BOB_CATCH_FUNCTION(message,ret) - Catches exceptions of any kind, adds the ``message`` in case an unknown exception is caught, and returns with the given error return (which is usually 0 for normal functions or -1 for constructors and setter functions). + Catches C++ exceptions of any kind, adds the ``message`` in case an unknown exception is caught, and returns with the given error return (which is usually 0 for normal functions or -1 for constructors and setter functions). This macro should be used when binding a stand-alone function, for binding class member functions, please use :c:macro:`BOB_CATCH_MEMBER`. .. c:macro:: BOB_CATCH_MEMBER(message,ret) - Catches exceptions of any kind, adds the ``message`` in case an unknown exception is caught, and returns with the given error return (which is usually 0 for normal functions or -1 for constructors and setter functions). + Catches C++ exceptions of any kind, adds the ``message`` in case an unknown exception is caught, and returns with the given error return (which is usually 0 for normal functions or -1 for constructors and setter functions). This macro should be used when binding a member function of a class, for binding stand-alone functions, please use :c:macro:`BOB_CATCH_FUNCTION`. +These preprocessor directives will catch any C++ exception that is raised inside the C/C++ code that you bind to python and translate them into proper Python exceptions. + +.. warning:: + These directives will only be active in **release** mode, when compiling with ``debug = true``, they will not do anything. + This is in order to support C++ debuggers like ``gdb`` or ``gdb-python`` to be able to handle these exceptions. + +Additionally, we added some preprocessor directives that help in the bindings: + .. c:macro:: PyBob_NumberCheck(o) Checks if the given object ``o`` is a number, i.e., an int, a long, a float or a complex. -After including the above mentioned header, we also re-define the functions :c:func:`PyInt_Check`, :c:func:` PyInt_AS_LONG`, :c:func:`PyString_Check` and :c:func:`PyString_AS_STRING` (which don't exist in the bindings for Python3) so that they can be used in bindings for both Python2 and Python3. +After including the above mentioned header, we also re-define the functions :c:func:`PyInt_Check`, :c:func:`PyInt_AS_LONG`, :c:func:`PyString_Check` and :c:func:`PyString_AS_STRING` (which don't exist in the bindings for Python3) so that they can be used in bindings for both Python2 and Python3. .. _cpp_api: diff --git a/doc/extension.rst b/doc/extension.rst index a92e83b..a013946 100644 --- a/doc/extension.rst +++ b/doc/extension.rst @@ -131,8 +131,14 @@ Finally, the function ``reverse`` from the module ``_library`` is imported into 1. We use a :c:macro:`BOB_TRY` and :c:macro:`BOB_CATCH_FUNCTION` block around the function call, as explained in :ref:`helpers`. + .. warning:: + By choosing ``debug = true`` in your ``buildout.cfg`` (which is the **default**, see below), the :ref:`C++ exception handling <helpers>` will be disabled (in order to support debuggers like ``gdb`` or ``gdb-python`` to handle these exceptions properly). + This will result in any C++ exception to be handled by the default C++ exception handler, which reports the exception in the console and stop the program (including any running python shells). + 2. We use a :cpp:class:`bob::extension::FunctionDoc` to generate a proper function documentation in Python, as explained in :ref:`docs`. + + To compile your C++ Python bindings and the pure C++ libraries, you can follow the same instructions as shown above: .. code-block:: sh @@ -143,9 +149,9 @@ To compile your C++ Python bindings and the pure C++ libraries, you can follow t ... .. note:: + By default, we compile the source code (of this and **all dependent packages**, both the ones installed as ``eggs``, and the ones developed using ``mr.developer``) in debug mode. + If you want to change that, switch the according flag in the ``buildout.cfg`` to ``debug = False``, and the compilation will be done with optimization flags and C++ exception handling enabled. - By default, we compile the source code (of this and all dependent packages) in debug mode. - If you want to change that, switch the according flag in the ``buildout.cfg`` to ``debug = False``, and the compilation will be done with optimization flags enabled. Now, we can use the script ``./bin/reverse.py`` (that we have registered in the ``setup.py``) to reverse a list of floats, using the C++ implementation of the ``reverse`` function: diff --git a/doc/guide.rst b/doc/guide.rst index cbe2df7..cb93a44 100644 --- a/doc/guide.rst +++ b/doc/guide.rst @@ -232,10 +232,10 @@ Some of the entries need attention. There, you can list directories that contain Python packages, which will be build in exactly the order that you specified there. With this option, you can tell buildout particularly, in which directories it should look for some packages. Note that the ``develop``ed packages are not automatically included into the ``eggs``. - Of course, you need to develop the current package, which is stored in directory ``.``. + Of course, you need to develop the current package, which is stored in ``.`` i.e, the current directory. The remaining options define, how the packages are build. -For example, the ``debug`` flag defined, how the C++ code in all the packages is built. +For example, the ``debug`` flag defined, how the :ref:`C++ code <extension-c++>` in all the packages is built. The ``verbose`` options handles the verbosity of the build. When the ``newest`` flag is set to ``true``, buildout will install all packages in the latest versions, even if an older version is already available. diff --git a/version.txt b/version.txt index a75b169..1a78b34 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.0.12b1 \ No newline at end of file +2.1.0b0 -- GitLab