mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 14:45:12 +00:00
FAQ improvements
This commit is contained in:
parent
8cb6cb33ef
commit
c79dbe425d
@ -5,7 +5,7 @@ Changelog
|
||||
|
||||
1.5 (not yet released)
|
||||
----------------------
|
||||
* For polymorphic types, use RTTI to try to return the closest type registered with pybind11.
|
||||
* For polymorphic types, use RTTI to try to return the closest type registered with pybind11
|
||||
* Pickling support for serializing and unserializing C++ instances to a byte stream in Python
|
||||
* Added a convenience routine ``make_iterator()`` which turns a range indicated
|
||||
by a pair of C++ iterators into a iterable Python object
|
||||
|
98
docs/faq.rst
98
docs/faq.rst
@ -97,3 +97,101 @@ that that were ``malloc()``-ed in another shared library, using data
|
||||
structures with incompatible ABIs, and so on. pybind11 is very careful not
|
||||
to make these types of mistakes.
|
||||
|
||||
How can I reduce the build time?
|
||||
================================
|
||||
|
||||
It's good practice to split binding code over multiple files, as is done in
|
||||
the included file :file:`example/example.cpp`.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void init_ex1(py::module &);
|
||||
void init_ex2(py::module &);
|
||||
/* ... */
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind example plugin");
|
||||
|
||||
init_ex1(m);
|
||||
init_ex2(m);
|
||||
|
||||
/* ... */
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
The various ``init_ex`` functions are contained in separate files that can be
|
||||
compiled independently from another. Following this approach will
|
||||
|
||||
1. enable parallel builds (if desired).
|
||||
|
||||
2. allow for faster incremental builds (e.g. if a single class definiton is
|
||||
changed, only a subset of the binding code may need to be recompiled).
|
||||
|
||||
3. reduce memory requirements.
|
||||
|
||||
How can I create smaller binaries?
|
||||
==================================
|
||||
|
||||
To do its job, pybind11 extensively relies on a programming technique known as
|
||||
*template metaprogramming*, which is a way of performing computation at compile
|
||||
time using type information. Template metaprogamming usually instantiates code
|
||||
involving significant numbers of deeply nested types that are either completely
|
||||
removed or reduced to just a few instrutions during the compiler's optimization
|
||||
phase. However, due to the nested nature of these types, the resulting symbol
|
||||
names in the compiled extension library can be extremely long. For instance,
|
||||
the included test suite contains the following symbol:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
__ZN8pybind1112cpp_functionC1Iv8Example2JRNSt3__16vectorINS3_12basic_stringIwNS3_11char_traitsIwEENS3_9allocatorIwEEEENS8_ISA_EEEEEJNS_4nameENS_7siblingENS_9is_methodEA28_cEEEMT0_FT_DpT1_EDpRKT2_
|
||||
|
||||
which is the mangled form of the following function type:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
pybind11::cpp_function::cpp_function<void, Example2, std::__1::vector<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, std::__1::allocator<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > > >&, pybind11::name, pybind11::sibling, pybind11::is_method, char [28]>(void (Example2::*)(std::__1::vector<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, std::__1::allocator<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > > >&), pybind11::name const&, pybind11::sibling const&, pybind11::is_method const&, char const (&) [28])
|
||||
|
||||
The memory needed to store just the name of this function (196 bytes) is larger
|
||||
than the actual piece of code (111 bytes) it represents! On the other hand,
|
||||
it's silly to even give this function a name -- after all, it's just a tiny
|
||||
cog in a bigger piece of machinery that is not exposed to the outside world.
|
||||
So we'll generally only want to export symbols for those functions which are
|
||||
actually called from the outside.
|
||||
|
||||
This can be achieved by specifying the parameter ``-fvisibility=hidden`` to GCC
|
||||
and Clang, which sets the default symbol visibility to *hidden*. It's best to
|
||||
do this only for release builds, since the symbol names can be helpful in
|
||||
debugging sessions. On Visual Studio, symbols are already hidden by default, so
|
||||
nothing needs to be done there. Needless to say, this has a tremendous impact
|
||||
on the final binary size of the resulting extension library.
|
||||
|
||||
Another aspect that can require a fair bit of code are function signature
|
||||
descriptions. pybind11 automatically generates human-readable function
|
||||
signatures for docstrings, e.g.:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
| __init__(...)
|
||||
| __init__(*args, **kwargs)
|
||||
| Overloaded function.
|
||||
|
|
||||
| 1. __init__(example.Example1) -> NoneType
|
||||
|
|
||||
| Docstring for overload #1 goes here
|
||||
|
|
||||
| 2. __init__(example.Example1, int) -> NoneType
|
||||
|
|
||||
| Docstring for overload #2 goes here
|
||||
|
|
||||
| 3. __init__(example.Example1, example.Example1) -> NoneType
|
||||
|
|
||||
| Docstring for overload #3 goes here
|
||||
|
||||
|
||||
In C++11 mode, these are generated at run time using string concatenation,
|
||||
which can amount to 10-20% of the size of the resulting binary. If you can,
|
||||
enable C++14 language features (using ``-std=c++14`` for GCC/Clang), in which
|
||||
case signatures are efficiently pre-generated at compile time. Unfortunately,
|
||||
Visual Studio's C++14 support (``constexpr``) is not good enough as of April
|
||||
2016, so it always uses the more expensive run-time approach.
|
||||
|
Loading…
Reference in New Issue
Block a user