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
cc88aaec
Commit
cc88aaec
authored
Jan 31, 2017
by
Pim Schellart
Committed by
Wenzel Jakob
Jan 31, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add check for matching holder_type when inheriting (#588)
parent
7830e850
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
53 additions
and
1 deletions
+53
-1
include/pybind11/attr.h
+12
-0
include/pybind11/cast.h
+2
-0
include/pybind11/pybind11.h
+2
-0
tests/test_inheritance.cpp
+17
-0
tests/test_inheritance.py
+20
-1
No files found.
include/pybind11/attr.h
View file @
cc88aaec
...
@@ -185,6 +185,9 @@ struct type_record {
...
@@ -185,6 +185,9 @@ struct type_record {
/// Does the class require its own metaclass?
/// Does the class require its own metaclass?
bool
metaclass
:
1
;
bool
metaclass
:
1
;
/// Is the default (unique_ptr) holder type used?
bool
default_holder
:
1
;
PYBIND11_NOINLINE
void
add_base
(
const
std
::
type_info
*
base
,
void
*
(
*
caster
)(
void
*
))
{
PYBIND11_NOINLINE
void
add_base
(
const
std
::
type_info
*
base
,
void
*
(
*
caster
)(
void
*
))
{
auto
base_info
=
detail
::
get_type_info
(
*
base
,
false
);
auto
base_info
=
detail
::
get_type_info
(
*
base
,
false
);
if
(
!
base_info
)
{
if
(
!
base_info
)
{
...
@@ -194,6 +197,15 @@ struct type_record {
...
@@ -194,6 +197,15 @@ struct type_record {
"
\"
referenced unknown base type
\"
"
+
tname
+
"
\"
"
);
"
\"
referenced unknown base type
\"
"
+
tname
+
"
\"
"
);
}
}
if
(
default_holder
!=
base_info
->
default_holder
)
{
std
::
string
tname
(
base
->
name
());
detail
::
clean_type_id
(
tname
);
pybind11_fail
(
"generic_type: type
\"
"
+
std
::
string
(
name
)
+
"
\"
"
+
(
default_holder
?
"does not have"
:
"has"
)
+
" a non-default holder type while its base
\"
"
+
tname
+
"
\"
"
+
(
base_info
->
default_holder
?
"does not"
:
"does"
));
}
bases
.
append
((
PyObject
*
)
base_info
->
type
);
bases
.
append
((
PyObject
*
)
base_info
->
type
);
if
(
base_info
->
type
->
tp_dictoffset
!=
0
)
if
(
base_info
->
type
->
tp_dictoffset
!=
0
)
...
...
include/pybind11/cast.h
View file @
cc88aaec
...
@@ -32,6 +32,8 @@ struct type_info {
...
@@ -32,6 +32,8 @@ struct type_info {
/** A simple type never occurs as a (direct or indirect) parent
/** A simple type never occurs as a (direct or indirect) parent
* of a class that makes use of multiple inheritance */
* of a class that makes use of multiple inheritance */
bool
simple_type
=
true
;
bool
simple_type
=
true
;
/* for base vs derived holder_type checks */
bool
default_holder
=
true
;
};
};
PYBIND11_NOINLINE
inline
internals
&
get_internals
()
{
PYBIND11_NOINLINE
inline
internals
&
get_internals
()
{
...
...
include/pybind11/pybind11.h
View file @
cc88aaec
...
@@ -741,6 +741,7 @@ protected:
...
@@ -741,6 +741,7 @@ protected:
tinfo
->
type_size
=
rec
->
type_size
;
tinfo
->
type_size
=
rec
->
type_size
;
tinfo
->
init_holder
=
rec
->
init_holder
;
tinfo
->
init_holder
=
rec
->
init_holder
;
tinfo
->
direct_conversions
=
&
internals
.
direct_conversions
[
tindex
];
tinfo
->
direct_conversions
=
&
internals
.
direct_conversions
[
tindex
];
tinfo
->
default_holder
=
rec
->
default_holder
;
internals
.
registered_types_cpp
[
tindex
]
=
tinfo
;
internals
.
registered_types_cpp
[
tindex
]
=
tinfo
;
internals
.
registered_types_py
[
type
]
=
tinfo
;
internals
.
registered_types_py
[
type
]
=
tinfo
;
...
@@ -1006,6 +1007,7 @@ public:
...
@@ -1006,6 +1007,7 @@ public:
record
.
instance_size
=
sizeof
(
instance_type
);
record
.
instance_size
=
sizeof
(
instance_type
);
record
.
init_holder
=
init_holder
;
record
.
init_holder
=
init_holder
;
record
.
dealloc
=
dealloc
;
record
.
dealloc
=
dealloc
;
record
.
default_holder
=
std
::
is_same
<
holder_type
,
std
::
unique_ptr
<
type
>>::
value
;
/* Register base classes specified via template arguments to class_, if any */
/* Register base classes specified via template arguments to class_, if any */
bool
unused
[]
=
{
(
add_base
<
options
>
(
record
),
false
)...,
false
};
bool
unused
[]
=
{
(
add_base
<
options
>
(
record
),
false
)...,
false
};
...
...
tests/test_inheritance.cpp
View file @
cc88aaec
...
@@ -49,6 +49,12 @@ struct BaseClass { virtual ~BaseClass() {} };
...
@@ -49,6 +49,12 @@ struct BaseClass { virtual ~BaseClass() {} };
struct
DerivedClass1
:
BaseClass
{
};
struct
DerivedClass1
:
BaseClass
{
};
struct
DerivedClass2
:
BaseClass
{
};
struct
DerivedClass2
:
BaseClass
{
};
struct
MismatchBase1
{
};
struct
MismatchDerived1
:
MismatchBase1
{
};
struct
MismatchBase2
{
};
struct
MismatchDerived2
:
MismatchBase2
{
};
test_initializer
inheritance
([](
py
::
module
&
m
)
{
test_initializer
inheritance
([](
py
::
module
&
m
)
{
py
::
class_
<
Pet
>
pet_class
(
m
,
"Pet"
);
py
::
class_
<
Pet
>
pet_class
(
m
,
"Pet"
);
pet_class
pet_class
...
@@ -97,4 +103,15 @@ test_initializer inheritance([](py::module &m) {
...
@@ -97,4 +103,15 @@ test_initializer inheritance([](py::module &m) {
py
::
isinstance
<
Unregistered
>
(
l
[
6
])
py
::
isinstance
<
Unregistered
>
(
l
[
6
])
);
);
});
});
m
.
def
(
"test_mismatched_holder_type_1"
,
[]()
{
auto
m
=
py
::
module
::
import
(
"__main__"
);
py
::
class_
<
MismatchBase1
,
std
::
shared_ptr
<
MismatchBase1
>>
(
m
,
"MismatchBase1"
);
py
::
class_
<
MismatchDerived1
,
MismatchBase1
>
(
m
,
"MismatchDerived1"
);
});
m
.
def
(
"test_mismatched_holder_type_2"
,
[]()
{
auto
m
=
py
::
module
::
import
(
"__main__"
);
py
::
class_
<
MismatchBase2
>
(
m
,
"MismatchBase2"
);
py
::
class_
<
MismatchDerived2
,
std
::
shared_ptr
<
MismatchDerived2
>
,
MismatchBase2
>
(
m
,
"MismatchDerived2"
);
});
});
});
tests/test_inheritance.py
View file @
cc88aaec
...
@@ -37,7 +37,8 @@ def test_automatic_upcasting():
...
@@ -37,7 +37,8 @@ def test_automatic_upcasting():
assert
type
(
return_class_1
())
.
__name__
==
"DerivedClass1"
assert
type
(
return_class_1
())
.
__name__
==
"DerivedClass1"
assert
type
(
return_class_2
())
.
__name__
==
"DerivedClass2"
assert
type
(
return_class_2
())
.
__name__
==
"DerivedClass2"
assert
type
(
return_none
())
.
__name__
==
"NoneType"
assert
type
(
return_none
())
.
__name__
==
"NoneType"
# Repeat these a few times in a random order to ensure no invalid caching is applied
# Repeat these a few times in a random order to ensure no invalid caching
# is applied
assert
type
(
return_class_n
(
1
))
.
__name__
==
"DerivedClass1"
assert
type
(
return_class_n
(
1
))
.
__name__
==
"DerivedClass1"
assert
type
(
return_class_n
(
2
))
.
__name__
==
"DerivedClass2"
assert
type
(
return_class_n
(
2
))
.
__name__
==
"DerivedClass2"
assert
type
(
return_class_n
(
0
))
.
__name__
==
"BaseClass"
assert
type
(
return_class_n
(
0
))
.
__name__
==
"BaseClass"
...
@@ -53,3 +54,21 @@ def test_isinstance():
...
@@ -53,3 +54,21 @@ def test_isinstance():
objects
=
[
tuple
(),
dict
(),
Pet
(
"Polly"
,
"parrot"
)]
+
[
Dog
(
"Molly"
)]
*
4
objects
=
[
tuple
(),
dict
(),
Pet
(
"Polly"
,
"parrot"
)]
+
[
Dog
(
"Molly"
)]
*
4
expected
=
(
True
,
True
,
True
,
True
,
True
,
False
,
False
)
expected
=
(
True
,
True
,
True
,
True
,
True
,
False
,
False
)
assert
test_isinstance
(
objects
)
==
expected
assert
test_isinstance
(
objects
)
==
expected
def
test_holder
():
from
pybind11_tests
import
test_mismatched_holder_type_1
,
test_mismatched_holder_type_2
with
pytest
.
raises
(
RuntimeError
)
as
excinfo
:
test_mismatched_holder_type_1
()
assert
str
(
excinfo
.
value
)
==
(
"generic_type: type
\"
MismatchDerived1
\"
does not have "
"a non-default holder type while its base "
"
\"
MismatchBase1
\"
does"
)
with
pytest
.
raises
(
RuntimeError
)
as
excinfo
:
test_mismatched_holder_type_2
()
assert
str
(
excinfo
.
value
)
==
(
"generic_type: type
\"
MismatchDerived2
\"
has a "
"non-default holder type while its base "
"
\"
MismatchBase2
\"
does not"
)
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