Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pybind11
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
pybind11
Commits
fe34241e
Commit
fe34241e
authored
Sep 06, 2016
by
Wenzel Jakob
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
minor doc & style fixes
parent
07082eec
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
220 additions
and
176 deletions
+220
-176
docs/advanced.rst
+135
-114
docs/basics.rst
+5
-5
docs/compiling.rst
+4
-4
docs/faq.rst
+1
-1
include/pybind11/cast.h
+1
-1
include/pybind11/pybind11.h
+1
-1
include/pybind11/stl_bind.h
+28
-25
tests/object.h
+1
-1
tests/test_callbacks.cpp
+1
-1
tests/test_eigen.cpp
+12
-12
tests/test_enum.cpp
+1
-1
tests/test_kwargs_and_defaults.cpp
+1
-1
tests/test_stl_binders.cpp
+10
-8
tools/check-style.sh
+19
-1
No files found.
docs/advanced.rst
View file @
fe34241e
...
@@ -551,27 +551,150 @@ and the Python ``list``, ``set`` and ``dict`` data structures are automatically
...
@@ -551,27 +551,150 @@ and the Python ``list``, ``set`` and ``dict`` data structures are automatically
enabled. The types ``std::pair<>`` and ``std::tuple<>`` are already supported
enabled. The types ``std::pair<>`` and ``std::tuple<>`` are already supported
out of the box with just the core :file:`pybind11/pybind11.h` header.
out of the box with just the core :file:`pybind11/pybind11.h` header.
Alternatively it might be desirable to bind STL containers as native C++ classes,
The major downside of these implicit conversions is that containers must be
eliminating the need of converting back and forth between C++ representation
converted (i.e. copied) on every Python->C++ and C++->Python transition, which
and Python one. The downside of this approach in this case users will have to
can have implications on the program semantics and performance. Please read the
deal with C++ containers directly instead of using already familiar Python lists
next sections for more details and alternative approaches that avoid this.
or dicts.
Pybind11 provide set of binder functions to bind various STL containers like vectors,
maps etc. All binder functions are designed to return instances of pybind11::class_
objects so developers can bind extra functions if needed. For complete set of
available functions please see :file:`pybind11/stl_bind.h`. For an example on using
this feature, please see :file:`tests/test_stl_binders.cpp`.
.. note::
.. note::
Arbitrary nesting of any of these types is
supported
.
Arbitrary nesting of any of these types is
possible
.
.. seealso::
.. seealso::
The file :file:`tests/test_python_types.cpp` contains a complete
The file :file:`tests/test_python_types.cpp` contains a complete
example that demonstrates how to pass STL data types in more detail.
example that demonstrates how to pass STL data types in more detail.
.. _opaque:
Treating STL data structures as opaque objects
==============================================
pybind11 heavily relies on a template matching mechanism to convert parameters
and return values that are constructed from STL data types such as vectors,
linked lists, hash tables, etc. This even works in a recursive manner, for
instance to deal with lists of hash maps of pairs of elementary and custom
types, etc.
However, a fundamental limitation of this approach is that internal conversions
between Python and C++ types involve a copy operation that prevents
pass-by-reference semantics. What does this mean?
Suppose we bind the following function
.. code-block:: cpp
void append_1(std::vector<int> &v) {
v.push_back(1);
}
and call it from Python, the following happens:
.. code-block:: pycon
>>> v = [5, 6]
>>> append_1(v)
>>> print(v)
[5, 6]
As you can see, when passing STL data structures by reference, modifications
are not propagated back the Python side. A similar situation arises when
exposing STL data structures using the ``def_readwrite`` or ``def_readonly``
functions:
.. code-block:: cpp
/* ... definition ... */
class MyClass {
std::vector<int> contents;
};
/* ... binding code ... */
py::class_<MyClass>(m, "MyClass")
.def(py::init<>)
.def_readwrite("contents", &MyClass::contents);
In this case, properties can be read and written in their entirety. However, an
``append`` operaton involving such a list type has no effect:
.. code-block:: pycon
>>> m = MyClass()
>>> m.contents = [5, 6]
>>> print(m.contents)
[5, 6]
>>> m.contents.append(7)
>>> print(m.contents)
[5, 6]
Finally, the involved copy operations can be costly when dealing with very
large lists. To deal with all of the above situations, pybind11 provides a
macro named ``PYBIND11_MAKE_OPAQUE(T)`` that disables the template-based
conversion machinery of types, thus rendering them *opaque*. The contents of
opaque objects are never inspected or extracted, hence they *can* be passed by
reference. For instance, to turn ``std::vector<int>`` into an opaque type, add
the declaration
.. code-block:: cpp
PYBIND11_MAKE_OPAQUE(std::vector<int>);
before any binding code (e.g. invocations to ``class_::def()``, etc.). This
macro must be specified at the top level (and outside of any namespaces), since
it instantiates a partial template overload. If your binding code consists of
multiple compilation units, it must be present in every file preceding any
usage of ``std::vector<int>``. Opaque types must also have a corresponding
``class_`` declaration to associate them with a name in Python, and to define a
set of available operations, e.g.:
.. code-block:: cpp
py::class_<std::vector<int>>(m, "IntVector")
.def(py::init<>())
.def("clear", &std::vector<int>::clear)
.def("pop_back", &std::vector<int>::pop_back)
.def("__len__", [](const std::vector<int> &v) { return v.size(); })
.def("__iter__", [](std::vector<int> &v) {
return py::make_iterator(v.begin(), v.end());
}, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */
// ....
The ability to expose STL containers as native Python objects is a fairly
common request, hence pybind11 also provides an optional header file named
:file:`pybind11/stl_bind.h` that does exactly this. The mapped containers try
to match the behavior of their native Python counterparts as much as possible.
The following example showcases usage of :file:`pybind11/stl_bind.h`:
.. code-block:: cpp
// Don't forget this
#include <pybind11/stl_bind.h>
PYBIND11_MAKE_OPAQUE(std::vector<int>);
PYBIND11_MAKE_OPAQUE(std::map<std::string, double>);
// ...
// later in binding code:
py::bind_vector<std::vector<int>>(m, "VectorInt");
py::bind_map<std::map<std::string, double>>(m, "MapStringDouble");
Please take a look at the :ref:`macro_notes` before using the
``PYBIND11_MAKE_OPAQUE`` macro.
.. seealso::
The file :file:`tests/test_opaque_types.cpp` contains a complete
example that demonstrates how to create and expose opaque types using
pybind11 in more detail.
The file :file:`tests/test_stl_binders.cpp` shows how to use the
convenience STL container wrappers.
Binding sequence data types, iterators, the slicing protocol, etc.
Binding sequence data types, iterators, the slicing protocol, etc.
==================================================================
==================================================================
...
@@ -1103,108 +1226,6 @@ section.
...
@@ -1103,108 +1226,6 @@ section.
The ``py::exception`` wrapper for creating custom exceptions cannot (yet)
The ``py::exception`` wrapper for creating custom exceptions cannot (yet)
be used as a ``py::base``.
be used as a ``py::base``.
.. _opaque:
Treating STL data structures as opaque objects
==============================================
pybind11 heavily relies on a template matching mechanism to convert parameters
and return values that are constructed from STL data types such as vectors,
linked lists, hash tables, etc. This even works in a recursive manner, for
instance to deal with lists of hash maps of pairs of elementary and custom
types, etc.
However, a fundamental limitation of this approach is that internal conversions
between Python and C++ types involve a copy operation that prevents
pass-by-reference semantics. What does this mean?
Suppose we bind the following function
.. code-block:: cpp
void append_1(std::vector<int> &v) {
v.push_back(1);
}
and call it from Python, the following happens:
.. code-block:: pycon
>>> v = [5, 6]
>>> append_1(v)
>>> print(v)
[5, 6]
As you can see, when passing STL data structures by reference, modifications
are not propagated back the Python side. A similar situation arises when
exposing STL data structures using the ``def_readwrite`` or ``def_readonly``
functions:
.. code-block:: cpp
/* ... definition ... */
class MyClass {
std::vector<int> contents;
};
/* ... binding code ... */
py::class_<MyClass>(m, "MyClass")
.def(py::init<>)
.def_readwrite("contents", &MyClass::contents);
In this case, properties can be read and written in their entirety. However, an
``append`` operaton involving such a list type has no effect:
.. code-block:: pycon
>>> m = MyClass()
>>> m.contents = [5, 6]
>>> print(m.contents)
[5, 6]
>>> m.contents.append(7)
>>> print(m.contents)
[5, 6]
To deal with both of the above situations, pybind11 provides a macro named
``PYBIND11_MAKE_OPAQUE(T)`` that disables the template-based conversion
machinery of types, thus rendering them *opaque*. The contents of opaque
objects are never inspected or extracted, hence they can be passed by
reference. For instance, to turn ``std::vector<int>`` into an opaque type, add
the declaration
.. code-block:: cpp
PYBIND11_MAKE_OPAQUE(std::vector<int>);
before any binding code (e.g. invocations to ``class_::def()``, etc.). This
macro must be specified at the top level, since instantiates a partial template
overload. If your binding code consists of multiple compilation units, it must
be present in every file preceding any usage of ``std::vector<int>``. Opaque
types must also have a corresponding ``class_`` declaration to associate them
with a name in Python, and to define a set of available operations:
.. code-block:: cpp
py::class_<std::vector<int>>(m, "IntVector")
.def(py::init<>())
.def("clear", &std::vector<int>::clear)
.def("pop_back", &std::vector<int>::pop_back)
.def("__len__", [](const std::vector<int> &v) { return v.size(); })
.def("__iter__", [](std::vector<int> &v) {
return py::make_iterator(v.begin(), v.end());
}, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */
// ....
Please take a look at the :ref:`macro_notes` before using this feature.
.. seealso::
The file :file:`tests/test_opaque_types.cpp` contains a complete
example that demonstrates how to create and expose opaque types using
pybind11 in more detail.
.. _eigen:
.. _eigen:
Transparent conversion of dense and sparse Eigen data types
Transparent conversion of dense and sparse Eigen data types
...
...
docs/basics.rst
View file @
fe34241e
...
@@ -178,16 +178,16 @@ The keyword names also appear in the function signatures within the documentatio
...
@@ -178,16 +178,16 @@ The keyword names also appear in the function signatures within the documentatio
A shorter notation for named arguments is also available:
A shorter notation for named arguments is also available:
.. code-block:: cpp
.. code-block:: cpp
// regular notation
// regular notation
m.def("add1", &add, py::arg("i"), py::arg("j"));
m.def("add1", &add, py::arg("i"), py::arg("j"));
// shorthand
// shorthand
using namespace pybind11::literals;
using namespace pybind11::literals;
m.def("add2", &add, "i"_a, "j"_a);
m.def("add2", &add, "i"_a, "j"_a);
The :var:`_a` suffix forms a C++11 literal which is equivalent to :class:`arg`.
The :var:`_a` suffix forms a C++11 literal which is equivalent to :class:`arg`.
Note that the literal operator must first be made visible with the directive
Note that the literal operator must first be made visible with the directive
``using namespace pybind11::literals``. This does not bring in anything else
``using namespace pybind11::literals``. This does not bring in anything else
from the ``pybind11`` namespace except for literals.
from the ``pybind11`` namespace except for literals.
.. _default_args:
.. _default_args:
...
@@ -229,7 +229,7 @@ The default values also appear within the documentation.
...
@@ -229,7 +229,7 @@ The default values also appear within the documentation.
The shorthand notation is also available for default arguments:
The shorthand notation is also available for default arguments:
.. code-block:: cpp
.. code-block:: cpp
// regular notation
// regular notation
m.def("add1", &add, py::arg("i") = 1, py::arg("j") = 2);
m.def("add1", &add, py::arg("i") = 1, py::arg("j") = 2);
// shorthand
// shorthand
...
...
docs/compiling.rst
View file @
fe34241e
...
@@ -26,7 +26,7 @@ Building with cppimport
...
@@ -26,7 +26,7 @@ Building with cppimport
Building with CMake
Building with CMake
===================
===================
For C++ codebases that have an existing CMake-based build system, a Python
For C++ codebases that have an existing CMake-based build system, a Python
extension module can be created with just a few lines of code:
extension module can be created with just a few lines of code:
.. code-block:: cmake
.. code-block:: cmake
...
@@ -37,14 +37,14 @@ extension module can be created with just a few lines of code:
...
@@ -37,14 +37,14 @@ extension module can be created with just a few lines of code:
add_subdirectory(pybind11)
add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)
pybind11_add_module(example example.cpp)
This assumes that the pybind11 repository is located in a subdirectory named
This assumes that the pybind11 repository is located in a subdirectory named
:file:`pybind11` and that the code is located in a file named :file:`example.cpp`.
:file:`pybind11` and that the code is located in a file named :file:`example.cpp`.
The CMake command ``add_subdirectory`` will import a function with the signature
The CMake command ``add_subdirectory`` will import a function with the signature
``pybind11_add_module(<name> source1 [source2 ...])``. It will take care of all
``pybind11_add_module(<name> source1 [source2 ...])``. It will take care of all
the details needed to build a Python extension module on any platform.
the details needed to build a Python extension module on any platform.
The target Python version can be selected by setting the ``PYBIND11_PYTHON_VERSION``
The target Python version can be selected by setting the ``PYBIND11_PYTHON_VERSION``
variable before adding the pybind11 subdirectory. Alternatively, an exact Python
variable before adding the pybind11 subdirectory. Alternatively, an exact Python
installation can be specified by setting ``PYTHON_EXECUTABLE``.
installation can be specified by setting ``PYTHON_EXECUTABLE``.
A working sample project, including a way to invoke CMake from :file:`setup.py` for
A working sample project, including a way to invoke CMake from :file:`setup.py` for
...
...
docs/faq.rst
View file @
fe34241e
...
@@ -140,7 +140,7 @@ the included test suite contains the following symbol:
...
@@ -140,7 +140,7 @@ the included test suite contains the following symbol:
.. code-block:: none
.. code-block:: none
__ZN8pybind1112cpp_functionC1Iv8Example2JRNSt3__16vectorINS3_12basic_stringIwNS3_11char_traitsIwEENS3_9allocatorIwEEEENS8_ISA_EEEEEJNS_4nameENS_7siblingENS_9is_methodEA28_cEEEMT0_FT_DpT1_EDpRKT2_
__ZN8pybind1112cpp_functionC1Iv8Example2JRNSt3__16vectorINS3_12basic_stringIwNS3_11char_traitsIwEENS3_9allocatorIwEEEENS8_ISA_EEEEEJNS_4nameENS_7siblingENS_9is_methodEA28_cEEEMT0_FT_DpT1_EDpRKT2_
.. only:: not html
.. only:: not html
...
...
include/pybind11/cast.h
View file @
fe34241e
...
@@ -681,7 +681,7 @@ public:
...
@@ -681,7 +681,7 @@ public:
static
PYBIND11_DESCR
element_names
()
{
static
PYBIND11_DESCR
element_names
()
{
return
detail
::
concat
(
type_caster
<
typename
intrinsic_type
<
Tuple
>::
type
>::
name
()...);
return
detail
::
concat
(
type_caster
<
typename
intrinsic_type
<
Tuple
>::
type
>::
name
()...);
}
}
static
PYBIND11_DESCR
name
()
{
static
PYBIND11_DESCR
name
()
{
return
type_descr
(
_
(
"Tuple["
)
+
element_names
()
+
_
(
"]"
));
return
type_descr
(
_
(
"Tuple["
)
+
element_names
()
+
_
(
"]"
));
}
}
...
...
include/pybind11/pybind11.h
View file @
fe34241e
...
@@ -1042,7 +1042,7 @@ public:
...
@@ -1042,7 +1042,7 @@ public:
def
(
"__ne__"
,
[](
const
Type
&
value
,
UnderlyingType
value2
)
{
return
(
UnderlyingType
)
value
!=
value2
;
});
def
(
"__ne__"
,
[](
const
Type
&
value
,
UnderlyingType
value2
)
{
return
(
UnderlyingType
)
value
!=
value2
;
});
}
}
def
(
"__hash__"
,
[](
const
Type
&
value
)
{
return
(
UnderlyingType
)
value
;
});
def
(
"__hash__"
,
[](
const
Type
&
value
)
{
return
(
UnderlyingType
)
value
;
});
// Pickling and unpickling -- needed for use with the 'multiprocessing' module
// Pickling and unpickling -- needed for use with the 'multiprocessing' module
def
(
"__getstate__"
,
[](
const
Type
&
value
)
{
return
pybind11
::
make_tuple
((
UnderlyingType
)
value
);
});
def
(
"__getstate__"
,
[](
const
Type
&
value
)
{
return
pybind11
::
make_tuple
((
UnderlyingType
)
value
);
});
def
(
"__setstate__"
,
[](
Type
&
p
,
tuple
t
)
{
new
(
&
p
)
Type
((
Type
)
t
[
0
].
cast
<
UnderlyingType
>
());
});
def
(
"__setstate__"
,
[](
Type
&
p
,
tuple
t
)
{
new
(
&
p
)
Type
((
Type
)
t
[
0
].
cast
<
UnderlyingType
>
());
});
m_entries
=
entries
;
m_entries
=
entries
;
...
...
include/pybind11/stl_bind.h
View file @
fe34241e
...
@@ -12,7 +12,6 @@
...
@@ -12,7 +12,6 @@
#include "common.h"
#include "common.h"
#include "operators.h"
#include "operators.h"
#include <map>
#include <type_traits>
#include <type_traits>
#include <utility>
#include <utility>
#include <algorithm>
#include <algorithm>
...
@@ -136,7 +135,7 @@ NAMESPACE_END(detail)
...
@@ -136,7 +135,7 @@ NAMESPACE_END(detail)
//
//
template
<
typename
Vector
,
typename
holder_type
=
std
::
unique_ptr
<
Vector
>
,
typename
...
Args
>
template
<
typename
Vector
,
typename
holder_type
=
std
::
unique_ptr
<
Vector
>
,
typename
...
Args
>
pybind11
::
class_
<
Vector
,
holder_type
>
bind_vector
(
pybind11
::
module
&
m
,
std
::
string
const
&
name
,
Args
&&
...
args
)
{
pybind11
::
class_
<
Vector
,
holder_type
>
bind_vector
(
pybind11
::
module
&
m
,
std
::
string
const
&
name
,
Args
&&
...
args
)
{
using
T
=
typename
Vector
::
value_type
;
using
T
=
typename
Vector
::
value_type
;
using
SizeType
=
typename
Vector
::
size_type
;
using
SizeType
=
typename
Vector
::
size_type
;
using
DiffType
=
typename
Vector
::
difference_type
;
using
DiffType
=
typename
Vector
::
difference_type
;
using
ItType
=
typename
Vector
::
iterator
;
using
ItType
=
typename
Vector
::
iterator
;
...
@@ -356,7 +355,7 @@ pybind11::class_<Vector, holder_type> bind_vector(pybind11::module &m, std::stri
...
@@ -356,7 +355,7 @@ pybind11::class_<Vector, holder_type> bind_vector(pybind11::module &m, std::stri
//
//
// std::map
// std::map
, std::unordered_map
//
//
NAMESPACE_BEGIN
(
detail
)
NAMESPACE_BEGIN
(
detail
)
...
@@ -373,8 +372,8 @@ template <typename Map, typename Class_, typename... Args> void map_if_copy_assi
...
@@ -373,8 +372,8 @@ template <typename Map, typename Class_, typename... Args> void map_if_copy_assi
auto
it
=
m
.
find
(
k
);
auto
it
=
m
.
find
(
k
);
if
(
it
!=
m
.
end
())
it
->
second
=
v
;
if
(
it
!=
m
.
end
())
it
->
second
=
v
;
else
m
.
emplace
(
k
,
v
);
else
m
.
emplace
(
k
,
v
);
}
);
}
);
}
}
template
<
typename
Map
,
typename
Class_
,
typename
std
::
enable_if
<!
std
::
is_copy_assignable
<
typename
Map
::
mapped_type
>::
value
,
int
>::
type
=
0
>
template
<
typename
Map
,
typename
Class_
,
typename
std
::
enable_if
<!
std
::
is_copy_assignable
<
typename
Map
::
mapped_type
>::
value
,
int
>::
type
=
0
>
...
@@ -384,12 +383,15 @@ void map_if_copy_assignable(Class_ &cl) {
...
@@ -384,12 +383,15 @@ void map_if_copy_assignable(Class_ &cl) {
cl
.
def
(
"__setitem__"
,
cl
.
def
(
"__setitem__"
,
[](
Map
&
m
,
const
KeyType
&
k
,
const
MappedType
&
v
)
{
[](
Map
&
m
,
const
KeyType
&
k
,
const
MappedType
&
v
)
{
auto
r
=
m
.
insert
(
std
::
make_pair
(
k
,
v
)
);
// We can't use m[k] = v; because value type might not be default constructable
// We can't use m[k] = v; because value type might not be default constructable
if
(
!
r
.
second
)
{
// value type might be const so the only way to insert it is to errase it first...
auto
r
=
m
.
insert
(
std
::
make_pair
(
k
,
v
));
if
(
!
r
.
second
)
{
// value type might be const so the only way to insert it is to erase it first...
m
.
erase
(
r
.
first
);
m
.
erase
(
r
.
first
);
m
.
insert
(
std
::
make_pair
(
k
,
v
)
);
m
.
insert
(
std
::
make_pair
(
k
,
v
)
);
}
}
});
}
);
}
}
...
@@ -401,8 +403,9 @@ template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ &
...
@@ -401,8 +403,9 @@ template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ &
std
::
ostringstream
s
;
std
::
ostringstream
s
;
s
<<
name
<<
'{'
;
s
<<
name
<<
'{'
;
bool
f
=
false
;
bool
f
=
false
;
for
(
auto
const
&
kv
:
m
)
{
for
(
auto
const
&
kv
:
m
)
{
if
(
f
)
s
<<
", "
;
if
(
f
)
s
<<
", "
;
s
<<
kv
.
first
<<
": "
<<
kv
.
second
;
s
<<
kv
.
first
<<
": "
<<
kv
.
second
;
f
=
true
;
f
=
true
;
}
}
...
@@ -428,17 +431,13 @@ pybind11::class_<Map, holder_type> bind_map(module &m, const std::string &name,
...
@@ -428,17 +431,13 @@ pybind11::class_<Map, holder_type> bind_map(module &m, const std::string &name,
detail
::
map_if_insertion_operator
<
Map
,
Class_
>
(
cl
,
name
);
detail
::
map_if_insertion_operator
<
Map
,
Class_
>
(
cl
,
name
);
cl
.
def
(
"__bool__"
,
cl
.
def
(
"__bool__"
,
[](
const
Map
&
m
)
->
bool
{
[](
const
Map
&
m
)
->
bool
{
return
!
m
.
empty
();
},
return
!
m
.
empty
();
},
"Check whether the map is nonempty"
"Check whether the map is nonempty"
);
);
cl
.
def
(
"__iter__"
,
cl
.
def
(
"__iter__"
,
[](
Map
&
m
)
{
[](
Map
&
m
)
{
return
pybind11
::
make_key_iterator
(
m
.
begin
(),
m
.
end
());
},
return
pybind11
::
make_key_iterator
(
m
.
begin
(),
m
.
end
());
pybind11
::
keep_alive
<
0
,
1
>
()
/* Essential: keep list alive while iterator exists */
},
pybind11
::
keep_alive
<
0
,
1
>
()
/* Essential: keep list alive while iterator exists */
);
);
cl
.
def
(
"items"
,
cl
.
def
(
"items"
,
...
@@ -449,18 +448,22 @@ pybind11::class_<Map, holder_type> bind_map(module &m, const std::string &name,
...
@@ -449,18 +448,22 @@ pybind11::class_<Map, holder_type> bind_map(module &m, const std::string &name,
cl
.
def
(
"__getitem__"
,
cl
.
def
(
"__getitem__"
,
[](
Map
&
m
,
const
KeyType
&
k
)
->
MappedType
{
[](
Map
&
m
,
const
KeyType
&
k
)
->
MappedType
{
auto
it
=
m
.
find
(
k
);
auto
it
=
m
.
find
(
k
);
if
(
it
!=
m
.
end
())
return
it
->
second
;
if
(
it
==
m
.
end
())
else
throw
pybind11
::
key_error
();
// it is not always possible to convert key to string // pybind11::key_error(k)
throw
pybind11
::
key_error
();
});
return
it
->
second
;
}
);
detail
::
map_if_copy_assignable
<
Map
,
Class_
>
(
cl
);
detail
::
map_if_copy_assignable
<
Map
,
Class_
>
(
cl
);
cl
.
def
(
"__delitem__"
,
cl
.
def
(
"__delitem__"
,
[](
Map
&
m
,
const
KeyType
&
k
)
{
[](
Map
&
m
,
const
KeyType
&
k
)
{
auto
it
=
m
.
find
(
k
);
auto
it
=
m
.
find
(
k
);
if
(
it
!=
m
.
end
())
return
m
.
erase
(
it
);
if
(
it
==
m
.
end
())
else
throw
pybind11
::
key_error
();
// it is not always possible to convert key to string // pybind11::key_error(k)
throw
pybind11
::
key_error
();
});
return
m
.
erase
(
it
);
}
);
cl
.
def
(
"__len__"
,
&
Map
::
size
);
cl
.
def
(
"__len__"
,
&
Map
::
size
);
...
...
tests/object.h
View file @
fe34241e
...
@@ -82,7 +82,7 @@ public:
...
@@ -82,7 +82,7 @@ public:
/// Move constructor
/// Move constructor
ref
(
ref
&&
r
)
:
m_ptr
(
r
.
m_ptr
)
{
ref
(
ref
&&
r
)
:
m_ptr
(
r
.
m_ptr
)
{
r
.
m_ptr
=
nullptr
;
r
.
m_ptr
=
nullptr
;
print_move_created
(
this
,
"with pointer"
,
m_ptr
);
track_move_created
((
ref_tag
*
)
this
);
print_move_created
(
this
,
"with pointer"
,
m_ptr
);
track_move_created
((
ref_tag
*
)
this
);
}
}
...
...
tests/test_callbacks.cpp
View file @
fe34241e
...
@@ -80,7 +80,7 @@ test_initializer callbacks([](py::module &m) {
...
@@ -80,7 +80,7 @@ test_initializer callbacks([](py::module &m) {
/* Test cleanup of lambda closure */
/* Test cleanup of lambda closure */
m
.
def
(
"test_cleanup"
,
[]()
->
std
::
function
<
void
(
void
)
>
{
m
.
def
(
"test_cleanup"
,
[]()
->
std
::
function
<
void
(
void
)
>
{
Payload
p
;
Payload
p
;
return
[
p
]()
{
return
[
p
]()
{
...
...
tests/test_eigen.cpp
View file @
fe34241e
...
@@ -84,51 +84,51 @@ test_initializer eigen([](py::module &m) {
...
@@ -84,51 +84,51 @@ test_initializer eigen([](py::module &m) {
return
m
.
selfadjointView
<
Eigen
::
Upper
>
();
return
m
.
selfadjointView
<
Eigen
::
Upper
>
();
});
});
m
.
def
(
"fixed_r"
,
[
mat
]()
->
FixedMatrixR
{
m
.
def
(
"fixed_r"
,
[
mat
]()
->
FixedMatrixR
{
return
FixedMatrixR
(
mat
);
return
FixedMatrixR
(
mat
);
});
});
m
.
def
(
"fixed_c"
,
[
mat
]()
->
FixedMatrixC
{
m
.
def
(
"fixed_c"
,
[
mat
]()
->
FixedMatrixC
{
return
FixedMatrixC
(
mat
);
return
FixedMatrixC
(
mat
);
});
});
m
.
def
(
"fixed_passthrough_r"
,
[](
const
FixedMatrixR
&
m
)
->
FixedMatrixR
{
m
.
def
(
"fixed_passthrough_r"
,
[](
const
FixedMatrixR
&
m
)
->
FixedMatrixR
{
return
m
;
return
m
;
});
});
m
.
def
(
"fixed_passthrough_c"
,
[](
const
FixedMatrixC
&
m
)
->
FixedMatrixC
{
m
.
def
(
"fixed_passthrough_c"
,
[](
const
FixedMatrixC
&
m
)
->
FixedMatrixC
{
return
m
;
return
m
;
});
});
m
.
def
(
"dense_r"
,
[
mat
]()
->
DenseMatrixR
{
m
.
def
(
"dense_r"
,
[
mat
]()
->
DenseMatrixR
{
return
DenseMatrixR
(
mat
);
return
DenseMatrixR
(
mat
);
});
});
m
.
def
(
"dense_c"
,
[
mat
]()
->
DenseMatrixC
{
m
.
def
(
"dense_c"
,
[
mat
]()
->
DenseMatrixC
{
return
DenseMatrixC
(
mat
);
return
DenseMatrixC
(
mat
);
});
});
m
.
def
(
"dense_passthrough_r"
,
[](
const
DenseMatrixR
&
m
)
->
DenseMatrixR
{
m
.
def
(
"dense_passthrough_r"
,
[](
const
DenseMatrixR
&
m
)
->
DenseMatrixR
{
return
m
;
return
m
;
});
});
m
.
def
(
"dense_passthrough_c"
,
[](
const
DenseMatrixC
&
m
)
->
DenseMatrixC
{
m
.
def
(
"dense_passthrough_c"
,
[](
const
DenseMatrixC
&
m
)
->
DenseMatrixC
{
return
m
;
return
m
;
});
});
m
.
def
(
"sparse_r"
,
[
mat
]()
->
SparseMatrixR
{
m
.
def
(
"sparse_r"
,
[
mat
]()
->
SparseMatrixR
{
return
Eigen
::
SparseView
<
Eigen
::
MatrixXf
>
(
mat
);
return
Eigen
::
SparseView
<
Eigen
::
MatrixXf
>
(
mat
);
});
});
m
.
def
(
"sparse_c"
,
[
mat
]()
->
SparseMatrixC
{
m
.
def
(
"sparse_c"
,
[
mat
]()
->
SparseMatrixC
{
return
Eigen
::
SparseView
<
Eigen
::
MatrixXf
>
(
mat
);
return
Eigen
::
SparseView
<
Eigen
::
MatrixXf
>
(
mat
);
});
});
m
.
def
(
"sparse_passthrough_r"
,
[](
const
SparseMatrixR
&
m
)
->
SparseMatrixR
{
m
.
def
(
"sparse_passthrough_r"
,
[](
const
SparseMatrixR
&
m
)
->
SparseMatrixR
{
return
m
;
return
m
;
});
});
m
.
def
(
"sparse_passthrough_c"
,
[](
const
SparseMatrixC
&
m
)
->
SparseMatrixC
{
m
.
def
(
"sparse_passthrough_c"
,
[](
const
SparseMatrixC
&
m
)
->
SparseMatrixC
{
return
m
;
return
m
;
});
});
});
});
tests/test_enum.cpp
View file @
fe34241e
...
@@ -25,7 +25,7 @@ public:
...
@@ -25,7 +25,7 @@ public:
EFirstMode
=
1
,
EFirstMode
=
1
,
ESecondMode
ESecondMode
};
};
static
EMode
test_function
(
EMode
mode
)
{
static
EMode
test_function
(
EMode
mode
)
{
return
mode
;
return
mode
;
}
}
...
...
tests/test_kwargs_and_defaults.cpp
View file @
fe34241e
...
@@ -59,7 +59,7 @@ test_initializer arg_keywords_and_defaults([](py::module &m) {
...
@@ -59,7 +59,7 @@ test_initializer arg_keywords_and_defaults([](py::module &m) {
using
namespace
py
::
literals
;
using
namespace
py
::
literals
;
m
.
def
(
"kw_func_udl"
,
&
kw_func
,
"x"
_a
,
"y"
_a
=
300
);
m
.
def
(
"kw_func_udl"
,
&
kw_func
,
"x"
_a
,
"y"
_a
=
300
);
m
.
def
(
"kw_func_udl_z"
,
&
kw_func
,
"x"
_a
,
"y"
_a
=
0
);
m
.
def
(
"kw_func_udl_z"
,
&
kw_func
,
"x"
_a
,
"y"
_a
=
0
);
py
::
class_
<
KWClass
>
(
m
,
"KWClass"
)
py
::
class_
<
KWClass
>
(
m
,
"KWClass"
)
.
def
(
"foo0"
,
&
KWClass
::
foo
)
.
def
(
"foo0"
,
&
KWClass
::
foo
)
.
def
(
"foo1"
,
&
KWClass
::
foo
,
"x"
_a
,
"y"
_a
);
.
def
(
"foo1"
,
&
KWClass
::
foo
,
"x"
_a
,
"y"
_a
);
...
...
tests/test_stl_binders.cpp
View file @
fe34241e
...
@@ -10,6 +10,8 @@
...
@@ -10,6 +10,8 @@
#include "pybind11_tests.h"
#include "pybind11_tests.h"
#include <pybind11/stl_bind.h>
#include <pybind11/stl_bind.h>
#include <map>
#include <unordered_map>
class
El
{
class
El
{
public
:
public
:
...
@@ -28,18 +30,18 @@ test_initializer stl_binder_vector([](py::module &m) {
...
@@ -28,18 +30,18 @@ test_initializer stl_binder_vector([](py::module &m) {
py
::
class_
<
El
>
(
m
,
"El"
)
py
::
class_
<
El
>
(
m
,
"El"
)
.
def
(
py
::
init
<
int
>
());
.
def
(
py
::
init
<
int
>
());
py
::
bind_vector
<
std
::
vector
<
unsigned
int
>
>
(
m
,
"VectorInt"
);
py
::
bind_vector
<
std
::
vector
<
unsigned
int
>
>
(
m
,
"VectorInt"
);
py
::
bind_vector
<
std
::
vector
<
bool
>
>
(
m
,
"VectorBool"
);
py
::
bind_vector
<
std
::
vector
<
bool
>
>
(
m
,
"VectorBool"
);
py
::
bind_vector
<
std
::
vector
<
El
>
>
(
m
,
"VectorEl"
);
py
::
bind_vector
<
std
::
vector
<
El
>
>
(
m
,
"VectorEl"
);
py
::
bind_vector
<
std
::
vector
<
std
::
vector
<
El
>
>
>
(
m
,
"VectorVectorEl"
);
py
::
bind_vector
<
std
::
vector
<
std
::
vector
<
El
>>
>
(
m
,
"VectorVectorEl"
);
});
});
test_initializer
stl_binder_map
([](
py
::
module
&
m
)
{
test_initializer
stl_binder_map
([](
py
::
module
&
m
)
{
py
::
bind_map
<
std
::
map
<
std
::
string
,
double
>
>
(
m
,
"MapStringDouble"
);
py
::
bind_map
<
std
::
map
<
std
::
string
,
double
>
>
(
m
,
"MapStringDouble"
);
py
::
bind_map
<
std
::
unordered_map
<
std
::
string
,
double
>
>
(
m
,
"UnorderedMapStringDouble"
);
py
::
bind_map
<
std
::
unordered_map
<
std
::
string
,
double
>
>
(
m
,
"UnorderedMapStringDouble"
);
py
::
bind_map
<
std
::
map
<
std
::
string
,
double
const
>
>
(
m
,
"MapStringDoubleConst"
);
py
::
bind_map
<
std
::
map
<
std
::
string
,
double
const
>
>
(
m
,
"MapStringDoubleConst"
);
py
::
bind_map
<
std
::
unordered_map
<
std
::
string
,
double
const
>
>
(
m
,
"UnorderedMapStringDoubleConst"
);
py
::
bind_map
<
std
::
unordered_map
<
std
::
string
,
double
const
>
>
(
m
,
"UnorderedMapStringDoubleConst"
);
});
});
tools/check-style.sh
View file @
fe34241e
#!/bin/bash
#!/bin/bash
#
#
# Script to check include/test code for common pybind11 code style errors.
# Script to check include/test code for common pybind11 code style errors.
# Currently just checks for tabs used instead of spaces.
#
# This script currently checks for
#
# 1. use of tabs instead of spaces
# 2. trailing spaces
# 3. missing space between keyword and parenthesis, e.g.: for(, if(, while(
#
#
# Invoke as: tools/check-style.sh
# Invoke as: tools/check-style.sh
#
#
...
@@ -22,6 +27,19 @@ while read -u 3 f; do
...
@@ -22,6 +27,19 @@ while read -u 3 f; do
done
done
found
=
found
=
# The mt=41 sets a red background for matched trailing spaces
exec
3< <
(
GREP_COLORS
=
'mt=41'
grep
'\s\+$'
include/ tests/
*
.
{
cpp,py,h
}
docs/
*
.rst
-rn
--color
=
always
)
while
read
-u
3 f
;
do
if
[
-z
"
$found
"
]
;
then
echo
-e
'\e[31m\e[01mError: found trailing spaces in the following files:\e[0m'
found
=
1
errors
=
1
fi
echo
"
$f
"
done
found
=
exec
3< <
(
grep
'\<\(if\|for\|while\)(\|){'
include/ tests/
*
.
{
cpp,py,h
}
-rn
--color
=
always
)
exec
3< <
(
grep
'\<\(if\|for\|while\)(\|){'
include/ tests/
*
.
{
cpp,py,h
}
-rn
--color
=
always
)
while
read
-u
3 line
;
do
while
read
-u
3 line
;
do
if
[
-z
"
$found
"
]
;
then
if
[
-z
"
$found
"
]
;
then
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment