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
77898af0
Commit
77898af0
authored
Oct 20, 2016
by
Wenzel Jakob
Committed by
GitHub
Oct 20, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #454 from dean0x7d/shared_ptr
Support std::shared_ptr holder type out of the box
parents
4f304461
5d28dd11
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
42 additions
and
36 deletions
+42
-36
docs/advanced/smart_ptrs.rst
+21
-25
docs/changelog.rst
+2
-0
include/pybind11/cast.h
+12
-6
include/pybind11/common.h
+4
-0
tests/test_class_args.cpp
+0
-1
tests/test_issues.cpp
+0
-1
tests/test_multiple_inheritance.cpp
+0
-1
tests/test_smart_ptr.cpp
+3
-2
No files found.
docs/advanced/smart_ptrs.rst
View file @
77898af0
Smart pointers
Smart pointers
##############
##############
Unique pointers
std::unique_ptr
===============
===============
Given a class ``Example`` with Python bindings, it's possible to return
Given a class ``Example`` with Python bindings, it's possible to return
...
@@ -28,14 +28,8 @@ The above signature would imply that Python needs to give up ownership of an
...
@@ -28,14 +28,8 @@ The above signature would imply that Python needs to give up ownership of an
object that is passed to this function, which is generally not possible (for
object that is passed to this function, which is generally not possible (for
instance, the object might be referenced elsewhere).
instance, the object might be referenced elsewhere).
.. _smart_pointers:
std::shared_ptr
===============
Reference-counting pointers
===========================
This section explains how to pass values that are wrapped in "smart" pointer
types with internal reference counting. For the simpler C++11 unique pointers,
refer to the previous section.
The binding generator for classes, :class:`class_`, can be passed a template
The binding generator for classes, :class:`class_`, can be passed a template
type that denotes a special *holder* type that is used to manage references to
type that denotes a special *holder* type that is used to manage references to
...
@@ -53,22 +47,6 @@ following snippet causes ``std::shared_ptr`` to be used instead.
...
@@ -53,22 +47,6 @@ following snippet causes ``std::shared_ptr`` to be used instead.
Note that any particular class can only be associated with a single holder type.
Note that any particular class can only be associated with a single holder type.
To enable transparent conversions for functions that take shared pointers as an
argument or that return them, a macro invocation similar to the following must
be declared at the top level before any binding code:
.. code-block:: cpp
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);
.. note::
The first argument of :func:`PYBIND11_DECLARE_HOLDER_TYPE` should be a
placeholder name that is used as a template parameter of the second
argument. Thus, feel free to use any identifier, but use it consistently on
both sides; also, don't use the name of a type that already exists in your
codebase.
One potential stumbling block when using holder types is that they need to be
One potential stumbling block when using holder types is that they need to be
applied consistently. Can you guess what's broken about the following binding
applied consistently. Can you guess what's broken about the following binding
code?
code?
...
@@ -139,6 +117,24 @@ There are two ways to resolve this issue:
...
@@ -139,6 +117,24 @@ There are two ways to resolve this issue:
class Child : public std::enable_shared_from_this<Child> { };
class Child : public std::enable_shared_from_this<Child> { };
.. _smart_pointers:
Custom smart pointers
=====================
pybind11 supports ``std::unique_ptr`` and ``std::shared_ptr`` right out of the
box. For any other custom smart pointer, transparent conversions can be enabled
using a macro invocation similar to the following. It must be declared at the
level before any binding code:
.. code-block:: cpp
PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>);
The first argument of :func:`PYBIND11_DECLARE_HOLDER_TYPE` should be a
placeholder name that is used as a template parameter of the second argument.
Thus, feel free to use any identifier, but use it consistently on both sides;
also, don't use the name of a type that already exists in your codebase.
Please take a look at the :ref:`macro_notes` before using this feature.
Please take a look at the :ref:`macro_notes` before using this feature.
...
...
docs/changelog.rst
View file @
77898af0
...
@@ -55,6 +55,8 @@ Breaking changes queued for v2.0.0 (Not yet released)
...
@@ -55,6 +55,8 @@ Breaking changes queued for v2.0.0 (Not yet released)
``py::str s = "1 + 2 = {}"_s.format(3);``
``py::str s = "1 + 2 = {}"_s.format(3);``
* Attribute and item accessors now have a more complete interface which makes it possible
* Attribute and item accessors now have a more complete interface which makes it possible
to chain attributes ``obj.attr("a")[key].attr("b").attr("method")(1, 2, 3)```.
to chain attributes ``obj.attr("a")[key].attr("b").attr("method")(1, 2, 3)```.
* Added built-in support for ``std::shared_ptr`` holder type. There is no more need
to do it manually via ``PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)``.
* Various minor improvements of library internals (no user-visible changes)
* Various minor improvements of library internals (no user-visible changes)
1.8.1 (July 12, 2016)
1.8.1 (July 12, 2016)
...
...
include/pybind11/cast.h
View file @
77898af0
...
@@ -383,12 +383,6 @@ public:
...
@@ -383,12 +383,6 @@ public:
operator type&() { return value; } \
operator type&() { return value; } \
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>
#define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type) \
namespace pybind11 { namespace detail { \
template <typename type> class type_caster<holder_type> \
: public type_caster_holder<type, holder_type> { }; \
}}
template
<
typename
T
>
template
<
typename
T
>
struct
type_caster
<
T
,
enable_if_t
<
std
::
is_arithmetic
<
T
>::
value
>>
{
struct
type_caster
<
T
,
enable_if_t
<
std
::
is_arithmetic
<
T
>::
value
>>
{
...
@@ -898,6 +892,18 @@ protected:
...
@@ -898,6 +892,18 @@ protected:
holder_type
holder
;
holder_type
holder
;
};
};
/// Specialize for the common std::shared_ptr, so users don't need to
template
<
typename
T
>
class
type_caster
<
std
::
shared_ptr
<
T
>>
:
public
type_caster_holder
<
T
,
std
::
shared_ptr
<
T
>>
{
};
/// Create a specialization for custom holder types (silently ignores std::shared_ptr)
#define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type) \
namespace pybind11 { namespace detail { \
template <typename type> \
class type_caster<holder_type, enable_if_t<!is_shared_ptr<holder_type>::value>> \
: public type_caster_holder<type, holder_type> { }; \
}}
// PYBIND11_DECLARE_HOLDER_TYPE holder types:
// PYBIND11_DECLARE_HOLDER_TYPE holder types:
template
<
typename
base
,
typename
holder
>
struct
is_holder_type
:
template
<
typename
base
,
typename
holder
>
struct
is_holder_type
:
std
::
is_base_of
<
detail
::
type_caster_holder
<
base
,
holder
>
,
detail
::
type_caster
<
holder
>>
{};
std
::
is_base_of
<
detail
::
type_caster_holder
<
base
,
holder
>
,
detail
::
type_caster
<
holder
>>
{};
...
...
include/pybind11/common.h
View file @
77898af0
...
@@ -417,6 +417,10 @@ using is_template_base_of = decltype(is_template_base_of_impl<Base>::check((T*)n
...
@@ -417,6 +417,10 @@ using is_template_base_of = decltype(is_template_base_of_impl<Base>::check((T*)n
struct
is_template_base_of
:
decltype
(
is_template_base_of_impl
<
Base
>::
check
((
T
*
)
nullptr
))
{
};
struct
is_template_base_of
:
decltype
(
is_template_base_of_impl
<
Base
>::
check
((
T
*
)
nullptr
))
{
};
#endif
#endif
/// Check if T is std::shared_ptr<U> where U can be anything
template
<
typename
T
>
struct
is_shared_ptr
:
std
::
false_type
{
};
template
<
typename
U
>
struct
is_shared_ptr
<
std
::
shared_ptr
<
U
>>
:
std
::
true_type
{
};
/// Ignore that a variable is unused in compiler warnings
/// Ignore that a variable is unused in compiler warnings
inline
void
ignore_unused
(
const
int
*
)
{
}
inline
void
ignore_unused
(
const
int
*
)
{
}
...
...
tests/test_class_args.cpp
View file @
77898af0
...
@@ -9,7 +9,6 @@
...
@@ -9,7 +9,6 @@
#include "pybind11_tests.h"
#include "pybind11_tests.h"
PYBIND11_DECLARE_HOLDER_TYPE
(
T
,
std
::
shared_ptr
<
T
>
);
template
<
int
N
>
class
BreaksBase
{};
template
<
int
N
>
class
BreaksBase
{};
template
<
int
N
>
class
BreaksTramp
:
public
BreaksBase
<
N
>
{};
template
<
int
N
>
class
BreaksTramp
:
public
BreaksBase
<
N
>
{};
...
...
tests/test_issues.cpp
View file @
77898af0
...
@@ -12,7 +12,6 @@
...
@@ -12,7 +12,6 @@
#include <pybind11/stl.h>
#include <pybind11/stl.h>
#include <pybind11/operators.h>
#include <pybind11/operators.h>
PYBIND11_DECLARE_HOLDER_TYPE
(
T
,
std
::
shared_ptr
<
T
>
);
#define TRACKERS(CLASS) CLASS() { print_default_created(this); } ~CLASS() { print_destroyed(this); }
#define TRACKERS(CLASS) CLASS() { print_default_created(this); } ~CLASS() { print_destroyed(this); }
struct
NestABase
{
int
value
=
-
2
;
TRACKERS
(
NestABase
)
};
struct
NestABase
{
int
value
=
-
2
;
TRACKERS
(
NestABase
)
};
...
...
tests/test_multiple_inheritance.cpp
View file @
77898af0
...
@@ -10,7 +10,6 @@
...
@@ -10,7 +10,6 @@
#include "pybind11_tests.h"
#include "pybind11_tests.h"
PYBIND11_DECLARE_HOLDER_TYPE
(
T
,
std
::
shared_ptr
<
T
>
);
struct
Base1
{
struct
Base1
{
Base1
(
int
i
)
:
i
(
i
)
{
}
Base1
(
int
i
)
:
i
(
i
)
{
}
...
...
tests/test_smart_ptr.cpp
View file @
77898af0
...
@@ -82,8 +82,9 @@ private:
...
@@ -82,8 +82,9 @@ private:
};
};
/// Make pybind aware of the ref-counted wrapper type (s)
/// Make pybind aware of the ref-counted wrapper type (s)
PYBIND11_DECLARE_HOLDER_TYPE
(
T
,
ref
<
T
>
);
PYBIND11_DECLARE_HOLDER_TYPE
(
T
,
ref
<
T
>
);
// Required for custom holder type
PYBIND11_DECLARE_HOLDER_TYPE
(
T
,
std
::
shared_ptr
<
T
>
);
PYBIND11_DECLARE_HOLDER_TYPE
(
T
,
std
::
shared_ptr
<
T
>
);
// Not required any more for std::shared_ptr,
// but it should compile without error
Object
*
make_object_1
()
{
return
new
MyObject1
(
1
);
}
Object
*
make_object_1
()
{
return
new
MyObject1
(
1
);
}
ref
<
Object
>
make_object_2
()
{
return
new
MyObject1
(
2
);
}
ref
<
Object
>
make_object_2
()
{
return
new
MyObject1
(
2
);
}
...
...
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