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
065d6820
Commit
065d6820
authored
Jan 21, 2021
by
Ralf W. Grosse-Kunstleve
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Changes and tests covering classh_type_casters try_implicit_casts.
parent
33711360
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
77 additions
and
17 deletions
+77
-17
include/pybind11/detail/classh_type_casters.h
+11
-8
tests/test_classh_inheritance.cpp
+44
-6
tests/test_classh_inheritance.py
+22
-3
No files found.
include/pybind11/detail/classh_type_casters.h
View file @
065d6820
...
@@ -58,7 +58,6 @@ public:
...
@@ -58,7 +58,6 @@ public:
}
}
bool
try_implicit_casts
(
handle
src
,
bool
convert
)
{
bool
try_implicit_casts
(
handle
src
,
bool
convert
)
{
pybind11_fail
(
"classh_type_casters: try_implicit_casts UNTESTED."
);
for
(
auto
&
cast
:
typeinfo
->
implicit_casts
)
{
for
(
auto
&
cast
:
typeinfo
->
implicit_casts
)
{
modified_type_caster_generic_load_impl
sub_caster
(
*
cast
.
first
);
modified_type_caster_generic_load_impl
sub_caster
(
*
cast
.
first
);
if
(
sub_caster
.
load
(
src
,
convert
))
{
if
(
sub_caster
.
load
(
src
,
convert
))
{
...
@@ -68,7 +67,6 @@ public:
...
@@ -68,7 +67,6 @@ public:
loaded_v_h
=
sub_caster
.
loaded_v_h
;
loaded_v_h
=
sub_caster
.
loaded_v_h
;
loaded_v_h_cpptype
=
cast
.
first
;
loaded_v_h_cpptype
=
cast
.
first
;
implicit_cast
=
cast
.
second
;
implicit_cast
=
cast
.
second
;
reinterpret_cast_ok
=
sub_caster
.
reinterpret_cast_ok
;
return
true
;
return
true
;
}
}
}
}
...
@@ -119,7 +117,6 @@ public:
...
@@ -119,7 +117,6 @@ public:
loaded_v_h
=
foreign_load_impl
->
loaded_v_h
;
loaded_v_h
=
foreign_load_impl
->
loaded_v_h
;
loaded_v_h_cpptype
=
foreign_load_impl
->
loaded_v_h_cpptype
;
loaded_v_h_cpptype
=
foreign_load_impl
->
loaded_v_h_cpptype
;
implicit_cast
=
foreign_load_impl
->
implicit_cast
;
implicit_cast
=
foreign_load_impl
->
implicit_cast
;
reinterpret_cast_ok
=
foreign_load_impl
->
reinterpret_cast_ok
;
return
true
;
return
true
;
}
}
return
false
;
return
false
;
...
@@ -163,7 +160,7 @@ public:
...
@@ -163,7 +160,7 @@ public:
if
(
bases
.
size
()
==
1
&&
(
no_cpp_mi
||
bases
.
front
()
->
type
==
typeinfo
->
type
))
{
if
(
bases
.
size
()
==
1
&&
(
no_cpp_mi
||
bases
.
front
()
->
type
==
typeinfo
->
type
))
{
this_
.
load_value_and_holder
(
reinterpret_cast
<
instance
*>
(
src
.
ptr
())
->
get_value_and_holder
());
this_
.
load_value_and_holder
(
reinterpret_cast
<
instance
*>
(
src
.
ptr
())
->
get_value_and_holder
());
loaded_v_h_cpptype
=
bases
.
front
()
->
cpptype
;
loaded_v_h_cpptype
=
bases
.
front
()
->
cpptype
;
reinterpret_cast_ok
=
true
;
reinterpret_cast_
deemed_
ok
=
true
;
return
true
;
return
true
;
}
}
// Case 2b: the python type inherits from multiple C++ bases. Check the bases to see if
// Case 2b: the python type inherits from multiple C++ bases. Check the bases to see if
...
@@ -175,7 +172,7 @@ public:
...
@@ -175,7 +172,7 @@ public:
if
(
no_cpp_mi
?
PyType_IsSubtype
(
base
->
type
,
typeinfo
->
type
)
:
base
->
type
==
typeinfo
->
type
)
{
if
(
no_cpp_mi
?
PyType_IsSubtype
(
base
->
type
,
typeinfo
->
type
)
:
base
->
type
==
typeinfo
->
type
)
{
this_
.
load_value_and_holder
(
reinterpret_cast
<
instance
*>
(
src
.
ptr
())
->
get_value_and_holder
(
base
));
this_
.
load_value_and_holder
(
reinterpret_cast
<
instance
*>
(
src
.
ptr
())
->
get_value_and_holder
(
base
));
loaded_v_h_cpptype
=
base
->
cpptype
;
loaded_v_h_cpptype
=
base
->
cpptype
;
reinterpret_cast_ok
=
true
;
reinterpret_cast_
deemed_
ok
=
true
;
return
true
;
return
true
;
}
}
}
}
...
@@ -219,7 +216,7 @@ public:
...
@@ -219,7 +216,7 @@ public:
const
std
::
type_info
*
loaded_v_h_cpptype
=
nullptr
;
const
std
::
type_info
*
loaded_v_h_cpptype
=
nullptr
;
void
*
(
*
implicit_cast
)(
void
*
)
=
nullptr
;
void
*
(
*
implicit_cast
)(
void
*
)
=
nullptr
;
value_and_holder
loaded_v_h
;
value_and_holder
loaded_v_h
;
bool
reinterpret_cast_ok
=
false
;
bool
reinterpret_cast_
deemed_
ok
=
false
;
};
};
// clang-format on
// clang-format on
...
@@ -238,8 +235,14 @@ struct smart_holder_type_caster_load {
...
@@ -238,8 +235,14 @@ struct smart_holder_type_caster_load {
}
}
T
*
as_raw_ptr_unowned
()
{
T
*
as_raw_ptr_unowned
()
{
if
(
load_impl
.
loaded_v_h_cpptype
!=
nullptr
&&
load_impl
.
reinterpret_cast_ok
)
{
if
(
load_impl
.
loaded_v_h_cpptype
!=
nullptr
)
{
return
reinterpret_cast
<
T
*>
(
loaded_smhldr_ptr
->
vptr
.
get
());
if
(
load_impl
.
reinterpret_cast_deemed_ok
)
{
return
static_cast
<
T
*>
(
loaded_smhldr_ptr
->
vptr
.
get
());
}
if
(
load_impl
.
implicit_cast
!=
nullptr
)
{
void
*
implicit_casted
=
load_impl
.
implicit_cast
(
loaded_smhldr_ptr
->
vptr
.
get
());
return
static_cast
<
T
*>
(
implicit_casted
);
}
}
}
return
loaded_smhldr_ptr
->
as_raw_ptr_unowned
<
T
>
();
return
loaded_smhldr_ptr
->
as_raw_ptr_unowned
<
T
>
();
}
}
...
...
tests/test_classh_inheritance.cpp
View file @
065d6820
...
@@ -5,22 +5,45 @@
...
@@ -5,22 +5,45 @@
namespace
pybind11_tests
{
namespace
pybind11_tests
{
namespace
classh_inheritance
{
namespace
classh_inheritance
{
struct
base
{
template
<
int
Id
>
base
()
:
base_id
(
100
)
{}
struct
base_template
{
virtual
~
base
()
=
default
;
base_template
()
:
base_id
(
Id
)
{}
virtual
~
base_template
()
=
default
;
virtual
int
id
()
const
{
return
base_id
;
}
virtual
int
id
()
const
{
return
base_id
;
}
int
base_id
;
int
base_id
;
};
};
using
base
=
base_template
<
100
>
;
struct
drvd
:
base
{
struct
drvd
:
base
{
int
id
()
const
override
{
return
2
*
base_id
;
}
int
id
()
const
override
{
return
2
*
base_id
;
}
};
};
inline
drvd
*
make_drvd
()
{
return
new
drvd
;
}
// clang-format off
inline
drvd
*
make_drvd
()
{
return
new
drvd
;
}
inline
base
*
make_drvd_up_cast
()
{
return
new
drvd
;
}
inline
base
*
make_drvd_up_cast
()
{
return
new
drvd
;
}
inline
int
pass_base
(
const
base
*
b
)
{
return
b
->
id
();
}
inline
int
pass_base
(
const
base
*
b
)
{
return
b
->
id
()
+
11
;
}
inline
int
pass_drvd
(
const
drvd
*
d
)
{
return
d
->
id
();
}
inline
int
pass_drvd
(
const
drvd
*
d
)
{
return
d
->
id
()
+
12
;
}
// clang-format on
using
base1
=
base_template
<
110
>
;
using
base2
=
base_template
<
120
>
;
// Not reusing base here because it would interfere with the single-inheritance test.
struct
drvd2
:
base1
,
base2
{
int
id
()
const
override
{
return
3
*
base1
::
base_id
+
4
*
base2
::
base_id
;
}
};
// clang-format off
inline
drvd2
*
make_drvd2
()
{
return
new
drvd2
;
}
inline
base1
*
make_drvd2_up_cast1
()
{
return
new
drvd2
;
}
inline
base2
*
make_drvd2_up_cast2
()
{
return
new
drvd2
;
}
inline
int
pass_base1
(
const
base1
*
b
)
{
return
b
->
id
()
+
21
;
}
inline
int
pass_base2
(
const
base2
*
b
)
{
return
b
->
id
()
+
22
;
}
inline
int
pass_drvd2
(
const
drvd2
*
d
)
{
return
d
->
id
()
+
23
;
}
// clang-format on
}
// namespace classh_inheritance
}
// namespace classh_inheritance
}
// namespace pybind11_tests
}
// namespace pybind11_tests
...
@@ -28,6 +51,10 @@ inline int pass_drvd(const drvd *d) { return d->id(); }
...
@@ -28,6 +51,10 @@ inline int pass_drvd(const drvd *d) { return d->id(); }
PYBIND11_CLASSH_TYPE_CASTERS
(
pybind11_tests
::
classh_inheritance
::
base
)
PYBIND11_CLASSH_TYPE_CASTERS
(
pybind11_tests
::
classh_inheritance
::
base
)
PYBIND11_CLASSH_TYPE_CASTERS
(
pybind11_tests
::
classh_inheritance
::
drvd
)
PYBIND11_CLASSH_TYPE_CASTERS
(
pybind11_tests
::
classh_inheritance
::
drvd
)
PYBIND11_CLASSH_TYPE_CASTERS
(
pybind11_tests
::
classh_inheritance
::
base1
)
PYBIND11_CLASSH_TYPE_CASTERS
(
pybind11_tests
::
classh_inheritance
::
base2
)
PYBIND11_CLASSH_TYPE_CASTERS
(
pybind11_tests
::
classh_inheritance
::
drvd2
)
namespace
pybind11_tests
{
namespace
pybind11_tests
{
namespace
classh_inheritance
{
namespace
classh_inheritance
{
...
@@ -39,6 +66,17 @@ TEST_SUBMODULE(classh_inheritance, m) {
...
@@ -39,6 +66,17 @@ TEST_SUBMODULE(classh_inheritance, m) {
m
.
def
(
"make_drvd_up_cast"
,
make_drvd_up_cast
,
py
::
return_value_policy
::
take_ownership
);
m
.
def
(
"make_drvd_up_cast"
,
make_drvd_up_cast
,
py
::
return_value_policy
::
take_ownership
);
m
.
def
(
"pass_base"
,
pass_base
);
m
.
def
(
"pass_base"
,
pass_base
);
m
.
def
(
"pass_drvd"
,
pass_drvd
);
m
.
def
(
"pass_drvd"
,
pass_drvd
);
py
::
classh
<
base1
>
(
m
,
"base1"
);
py
::
classh
<
base2
>
(
m
,
"base2"
);
py
::
classh
<
drvd2
,
base1
,
base2
>
(
m
,
"drvd2"
);
m
.
def
(
"make_drvd2"
,
make_drvd2
,
py
::
return_value_policy
::
take_ownership
);
m
.
def
(
"make_drvd2_up_cast1"
,
make_drvd2_up_cast1
,
py
::
return_value_policy
::
take_ownership
);
m
.
def
(
"make_drvd2_up_cast2"
,
make_drvd2_up_cast2
,
py
::
return_value_policy
::
take_ownership
);
m
.
def
(
"pass_base1"
,
pass_base1
);
m
.
def
(
"pass_base2"
,
pass_base2
);
m
.
def
(
"pass_drvd2"
,
pass_drvd2
);
}
}
}
// namespace classh_inheritance
}
// namespace classh_inheritance
...
...
tests/test_classh_inheritance.py
View file @
065d6820
...
@@ -5,8 +5,8 @@ from pybind11_tests import classh_inheritance as m
...
@@ -5,8 +5,8 @@ from pybind11_tests import classh_inheritance as m
def
test_make_drvd_pass_base
():
def
test_make_drvd_pass_base
():
d
=
m
.
make_drvd
()
d
=
m
.
make_drvd
()
i
=
m
.
pass_base
(
d
)
i
=
m
.
pass_base
(
d
)
# load_impl Case 2a
assert
i
==
2
00
assert
i
==
2
*
100
+
11
def
test_make_drvd_up_cast_pass_drvd
():
def
test_make_drvd_up_cast_pass_drvd
():
...
@@ -14,4 +14,23 @@ def test_make_drvd_up_cast_pass_drvd():
...
@@ -14,4 +14,23 @@ def test_make_drvd_up_cast_pass_drvd():
# the base return is down-cast immediately.
# the base return is down-cast immediately.
assert
b
.
__class__
.
__name__
==
"drvd"
assert
b
.
__class__
.
__name__
==
"drvd"
i
=
m
.
pass_drvd
(
b
)
i
=
m
.
pass_drvd
(
b
)
assert
i
==
200
assert
i
==
2
*
100
+
12
def
test_make_drvd2_pass_bases
():
d
=
m
.
make_drvd2
()
i1
=
m
.
pass_base1
(
d
)
# load_impl Case 2c
assert
i1
==
3
*
110
+
4
*
120
+
21
i2
=
m
.
pass_base2
(
d
)
assert
i2
==
3
*
110
+
4
*
120
+
22
def
test_make_drvd2_up_casts_pass_drvd2
():
b1
=
m
.
make_drvd2_up_cast1
()
assert
b1
.
__class__
.
__name__
==
"drvd2"
i1
=
m
.
pass_drvd2
(
b1
)
assert
i1
==
3
*
110
+
4
*
120
+
23
b2
=
m
.
make_drvd2_up_cast2
()
assert
b2
.
__class__
.
__name__
==
"drvd2"
i2
=
m
.
pass_drvd2
(
b2
)
assert
i2
==
3
*
110
+
4
*
120
+
23
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