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
8ed5b8ab
Commit
8ed5b8ab
authored
Aug 28, 2017
by
Wenzel Jakob
Committed by
GitHub
Aug 28, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
make implicit conversions non-reentrant (fixes #1035) (#1037)
parent
15f36d2b
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
34 additions
and
0 deletions
+34
-0
docs/advanced/classes.rst
+4
-0
include/pybind11/pybind11.h
+9
-0
tests/test_class.cpp
+11
-0
tests/test_class.py
+10
-0
No files found.
docs/advanced/classes.rst
View file @
8ed5b8ab
...
@@ -585,6 +585,10 @@ Python side:
...
@@ -585,6 +585,10 @@ Python side:
Implicit conversions from ``A`` to ``B`` only work when ``B`` is a custom
Implicit conversions from ``A`` to ``B`` only work when ``B`` is a custom
data type that is exposed to Python via pybind11.
data type that is exposed to Python via pybind11.
To prevent runaway recursion, implicit conversions are non-reentrant: an
implicit conversion invoked as part of another implicit conversion of the
same type (i.e. from ``A`` to ``B``) will fail.
.. _static_properties:
.. _static_properties:
Static properties
Static properties
...
...
include/pybind11/pybind11.h
View file @
8ed5b8ab
...
@@ -1536,7 +1536,16 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
...
@@ -1536,7 +1536,16 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
}
}
template
<
typename
InputType
,
typename
OutputType
>
void
implicitly_convertible
()
{
template
<
typename
InputType
,
typename
OutputType
>
void
implicitly_convertible
()
{
struct
set_flag
{
bool
&
flag
;
set_flag
(
bool
&
flag
)
:
flag
(
flag
)
{
flag
=
true
;
}
~
set_flag
()
{
flag
=
false
;
}
};
auto
implicit_caster
=
[](
PyObject
*
obj
,
PyTypeObject
*
type
)
->
PyObject
*
{
auto
implicit_caster
=
[](
PyObject
*
obj
,
PyTypeObject
*
type
)
->
PyObject
*
{
static
bool
currently_used
=
false
;
if
(
currently_used
)
// implicit conversions are non-reentrant
return
nullptr
;
set_flag
flag_helper
(
currently_used
);
if
(
!
detail
::
make_caster
<
InputType
>
().
load
(
obj
,
false
))
if
(
!
detail
::
make_caster
<
InputType
>
().
load
(
obj
,
false
))
return
nullptr
;
return
nullptr
;
tuple
args
(
1
);
tuple
args
(
1
);
...
...
tests/test_class.cpp
View file @
8ed5b8ab
...
@@ -291,6 +291,17 @@ TEST_SUBMODULE(class_, m) {
...
@@ -291,6 +291,17 @@ TEST_SUBMODULE(class_, m) {
.
def
(
py
::
init
<
int
,
const
std
::
string
&>
())
.
def
(
py
::
init
<
int
,
const
std
::
string
&>
())
.
def_readwrite
(
"field1"
,
&
BraceInitialization
::
field1
)
.
def_readwrite
(
"field1"
,
&
BraceInitialization
::
field1
)
.
def_readwrite
(
"field2"
,
&
BraceInitialization
::
field2
);
.
def_readwrite
(
"field2"
,
&
BraceInitialization
::
field2
);
// test_reentrant_implicit_conversion_failure
// #1035: issue with runaway reentrant implicit conversion
struct
BogusImplicitConversion
{
BogusImplicitConversion
(
const
BogusImplicitConversion
&
)
{
}
};
py
::
class_
<
BogusImplicitConversion
>
(
m
,
"BogusImplicitConversion"
)
.
def
(
py
::
init
<
const
BogusImplicitConversion
&>
());
py
::
implicitly_convertible
<
int
,
BogusImplicitConversion
>
();
}
}
template
<
int
N
>
class
BreaksBase
{
public
:
virtual
~
BreaksBase
()
=
default
;
};
template
<
int
N
>
class
BreaksBase
{
public
:
virtual
~
BreaksBase
()
=
default
;
};
...
...
tests/test_class.py
View file @
8ed5b8ab
...
@@ -223,3 +223,13 @@ def test_class_refcount():
...
@@ -223,3 +223,13 @@ def test_class_refcount():
assert
refcount_1
==
refcount_3
assert
refcount_1
==
refcount_3
assert
refcount_2
>
refcount_1
assert
refcount_2
>
refcount_1
def
test_reentrant_implicit_conversion_failure
(
msg
):
# ensure that there is no runaway reentrant implicit conversion (#1035)
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
m
.
BogusImplicitConversion
(
0
)
assert
msg
(
excinfo
.
value
)
==
'''__init__(): incompatible constructor arguments. The following argument types are supported:
1. m.class_.BogusImplicitConversion(arg0: m.class_.BogusImplicitConversion)
Invoked with: 0'''
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