Commit ef761df8 authored by Eric Cousineau's avatar Eric Cousineau
Browse files

README: Update atlernatives comparison

Rename "PyBind11" to "pybind11" (what the project actually uses)
parent a87a911e
......@@ -2,7 +2,7 @@ Wrapper Generator
==================
This repository contains the first set of Python code which could be used to
automatically generate PyBin11 code from C++ files with proper annotation.
automatically generate pybind11 code from C++ files with proper annotation.
**CAUTION**: The content, structure, and API of this repository are still under
development. No guarantees of backwards compatibility are given for the
......@@ -122,7 +122,7 @@ introduced into the environment. This repository contains the
find_package(AutoPyBind11)
After this command is found, one additional command will be used to acquire PyBind11 via the
After this command is found, one additional command will be used to acquire pybind11 via the
``FetchContent`` module::
autopybind11_fetch_build_pybind11()
......@@ -130,9 +130,9 @@ After this command is found, one additional command will be used to acquire PyBi
Add Library
%%%%%%%%%%%
To add a library for the written PyBind11 code, we use the ``autopybind11_add_module``
To add a library for the written pybind11 code, we use the ``autopybind11_add_module``
function. This function does the work of setting custom commands to generate
the PyBind11 code and adds a library to CMake which contains the PyBind11 code., and then
the pybind11 code and adds a library to CMake which contains the pybind11 code., and then
This command should be written once for each ``wrapper_input.yml`` file in the repository.
The command has the following structure::
......@@ -142,7 +142,7 @@ The command has the following structure::
[CONFIG_INPUT <path_to>/config.yml])
Only the ``CONFIG_INPUT`` flag is optional. The file given to that argument can be used
to customize the templates used to create the PyBind11 CPP code. The default templates
to customize the templates used to create the pybind11 CPP code. The default templates
can be found in `text_blocks.py`_
An example of the function invocation is here::
......@@ -190,7 +190,7 @@ The Python script has help for the arguments::
-y YAML_PATH, --input_yaml YAML_PATH
Path to input YAML file of objects to process
--module_name MODULE_NAME
Desired name of the output PyBind11 module
Desired name of the output pybind11 module
-g CASTXML_PATH, --castxml-path CASTXML_PATH
Path to castxml
-cg CONFIG_DIR, --config-path CONFIG_DIR
......@@ -234,35 +234,68 @@ or setup a CMake build system and execute the ``WG_Linter`` test::
$ ctest -R WG_Linter -VV
Previous Work:
------------------
Alternatives Comparison
-----------------------
CLIF
####
https://github.com/google/clif
Philosophically in some ways similar to the hooking up CastXML and some code
generator and runtime library (e.g., Pybind11), which would mean most of the
glue that would need to be written is already there. However, it is an
incomplete and apparently dead project (from a public point of view). Also,
no Numpy and Eigen support. It had a high profile developer in Google and there
were once some mentions of CLIF in the Bazel codebase.
Philosophically in some ways similar to hooking up CastXML (they use clang /
llvm as their C++ parser), a code generator (like this project), and a runtime
library for interfacing (like pybind11). This means mean most of the
glue that would need to be written is already there. It was originally written
as a general IDL (Interface Definition Language), which is great for
multi-language support (e.g. Python, MATLAB, etc), but will suffer when there
are language-specific foreign functional interfaces (FFIs).
However, it is an incomplete and currently dead project (from a public point of
view). Also, it has no Numpy and Eigen support. It had a high profile
developer in Google and there were once some mentions of CLIF in the Bazel
codebase.
Pybind11
This project may possibly resume at some point
(`drake#7889 <https://github.com/RobotLocomotion/drake/issues/7889#issuecomment-634260874>`_).
pybind11
########
Definitions are written in C++ code, which is also more familiar to developers
than some intermediate language (like SWIG). Pybind11 (but not Boost Python)
includes extensive Numpy and Eigen support that would take some time to
reimplement. Some features are missing and have been added via patches with
varying success (codebase is difficult to understand). Pybind11 upstream is
generally not responsive to patches (though obviously better than CLIF),
whether Boost Python would be more responsive is unknown.
Several open source projects are already working on generating Pybind11
.. note: This should be moved to the top.
https://pybind11.readthedocs.io/en/stable/
This is the "spiritual successor" to Boost.Python, and is a very popular Python
binding library.
Binding definitions are written in pure C++ code, which allows more familiarity
with developers, and slightly easier debugging (vs. interfaces like SWIG, where
you must debug both the binding generation *and* the runtime). pybind11 not
only provides a mechanism for exposing C++ to Python, but also provides its
Python C++ interface for exposing Python to C++.
pybind11 (but not Boost.Python) includes extensive builtin Numpy support with
C++ Eigen interface, ranging from interfacing with ``Eigen::Map<>`` to handling
sparse and dense arrays.
Some features are missing and have been added via patches with varying success
(in the author's opinion, the codebase may be difficult to understand).
pybind11 upstream is generally tentative about taking on major changes that
only benefit a few downstream projects, and at times can have a slow response
rate.
At present, there is an increasing trend of responses on the maintainer's part.
Several open source projects are already working on generating pybind11
bindings.
.. note::
As mentioned above, this project emits pybind11 C++ code, and is meant to
help minimize the minutae of writing high-quality bindings with pybind11.
SWIG
####
......@@ -271,23 +304,34 @@ http://www.swig.org/
Multi-language support would be an advantage. Projects in the open source
community already have code that generates SWIG bindings,
but the authors have stated that if they were starting now, they would use
Pybind11. The SWIG intermediate language is less familiar to Drake developers
than pure C++ and most Numpy and Eigen support would need to be written).
Upstream seems to be responsive, but potentially patches would need
to work for multiple languages that SWIG supports.
pybind11.
The SWIG intermediate language can be seen as a boon when the interfaces are
simple, but a bottleneck when more complexity is necessary -- a standard issue
with IDLs aiming towards providing FFIs.
The developers of `Drake`_ previously used SWIG, but then transitioned to
pybind11 due to its extensive NumPy and Eigen support, and the ability to
(relatively easily) fork the code to provide support for dynamic scalar types.
.. _`Drake`: https://drake.mit.edu/
CPPWG
#####
https://github.com/jmsgrogan/cppwg/
CPPWG was the first tool used in the attempt to wrap Drake code. This tool
was the inspiration for the structure of the AutoPyBind11 system. It uses
CPPWG was the first tool used in the attempt to automate Python bindings in
Drake (`drake#7889 <https://github.com/RobotLocomotion/drake/issues/7889>`_).
This tool was the inspiration for the structure of the AutoPyBind11 system. It
uses
CastXML with pygccxml and nested configuration files to denote what classes and
free functions needed to be wrapped by the tool. It also had a configurable set
of PyBind11 output, but with much less customization opportunity as the
of pybind11 output, but with much less customization opportunity as the
customization was limited to a few specific places in the code as opposed to
the structure of the PyBind11 code which AutoPyBind11 allows.
the structure of the pybind11 code which AutoPyBind11 allows.
The tool’s major shortcoming was the method’s handling of templated classes.
It used string matching while parsing the C++ source file to determine if
any of the lines found in the object required templating. Additionally,
......@@ -300,30 +344,76 @@ Binder
https://github.com/RosettaCommons/binder and https://cppbinder.readthedocs.io/en/latest/
Binder is another tool that performs the automatic wrapping of C++ code into
Python via PyBind11. It uses C++ as the language of the tool, as opposed to
Python via pybind11. It uses C++ as the language of the tool, as opposed to
AutoPyBind11 which uses Python. The Binder tool also uses a configuration file.
The system uses a “+/-” for inclusion and omission of the three basic objects:
namespaces, classes, and functions. Binder’s configuration file can also alter
the functions used to bind the code. The user can specify a function which is
run in place of the default binding code.
AutoWIG
#######
https://github.com/StatisKit/AutoWIG |
`Paper <https://arxiv.org/abs/1705.11000>`_ |
`Docs <https://autowig.readthedocs.io/en/latest/index.html>`_ |
`Example Code <https://github.com/StatisKit/FP17>`_
Provides a means to parse C++ code and emit either Boost.Python or pybind11
code, using libclang in Python(Python bindings of C API for Clang). It can also
translate docstrings from Doxygen to Sphinx, including symbol references.
It also provides a comprehensive class structure with different passes, which
look great for generalization, but may also cause developers some pain with
indirection via abstraction.
It's an impressive project, and the paper (cited above) has some interesting
comparisons (including a comparison of methods for VTK and ITK). However,
the current development is a bit unclear. The documentation seems most
comprehensive in the arXiv publication, but appears lacking in the ReadTheDocs
website.
PyBindGen
#########
https://pybindgen.readthedocs.io/en/latest/ and https://github.com/gjcarneiro/pybindgen
PyBindGen is a Python-only module that allows the specification of C++ modules
to wrap into PyBind11. It doesn’t rely on a configuration file to determine
what parts of the C++ code are wrapped but instead uses a Python script to
to wrap into custom Python runtime (not pybind11 code!).
It doesn’t rely on a configuration file to determine what parts of the C++ code
are wrapped but instead uses a Python script to
create the modules and add all objects. The compilation of the resultant code
is done via a “python setup.py” command and is what creates the PyBind11 code.
is done via a “python setup.py” command and is what creates the C++ code that
calls into the CPython API.
It does have some pygccxml integration. One mode of execution uses pygccxml to
parse C++ code and write the PyBind11 code into a separate file. The other
parse C++ code and write the pybind11 code into a separate file. The other
mode parses the header files but writes out the information into a PyBindGen
script.
Most notably, because this code generates its own bindings, any runtime
debugging must done jointly with the code generation, which would incur similar
overhead like debugging errors with SWIG.
Other Tools / Libraries
#######################
* https://github.com/robotpy/robotpy-build
- Only for RobotPy
- Emits pybind11 code
- Uses `header2whatever <https://pypi.org/project/header2whatever/>`_
* https://cppyy.readthedocs.io/en/latest/index.html
- Uses Cling (C++ interpreter) to generate Python bindings of C++ code on the
fly
- Due to usage of Cling, may heavily impact first-time usage (similar to
Julia)
.. _pycodestyle: https://pypi.org/project/pycodestyle/
.. _Copyright.txt: Copyright.txt
.. _`data.kitware.com`: https://data.kitware.com/#folder/57b5de948d777f10f2696370
.. _`text_blocks.py`: text_blocks.py
.. _`wrapper_input.yml`: example/wrapper_input.yml
\ No newline at end of file
.. _`wrapper_input.yml`: example/wrapper_input.yml
Supports Markdown
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