Skip to content

Commit 7ce1ad0

Browse files
show object slicing w/ pickling C++ derived object not visible to pybind
1 parent ef433dc commit 7ce1ad0

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

tests/test_pickling.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,19 @@ struct SimpleBase {
2626
// For compatibility with old clang versions:
2727
SimpleBase() = default;
2828
SimpleBase(const SimpleBase &) = default;
29+
30+
virtual int get_value_via_vtable() const { return 1; }
2931
};
3032

31-
struct SimpleBaseTrampoline : SimpleBase {};
33+
struct SimpleBaseTrampoline : SimpleBase {
34+
int get_value_via_vtable() const override {
35+
PYBIND11_OVERRIDE(int, SimpleBase, get_value_via_vtable);
36+
}
37+
};
3238

33-
struct SimpleCppDerived : SimpleBase {};
39+
struct SimpleCppDerived : SimpleBase {
40+
int get_value_via_vtable() const override { return 10; }
41+
};
3442

3543
void wrap(py::module m) {
3644
py::class_<SimpleBase, SimpleBaseTrampoline>(m, "SimpleBase")
@@ -54,6 +62,9 @@ void wrap(py::module m) {
5462

5563
m.def("make_SimpleCppDerivedAsBase",
5664
[]() { return std::unique_ptr<SimpleBase>(new SimpleCppDerived); });
65+
66+
m.def("get_value_via_vtable_cpp",
67+
[](const SimpleBase& obj) { return obj.get_value_via_vtable(); });
5768
}
5869

5970
} // namespace exercise_trampoline

tests/test_pickling.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,23 +51,28 @@ def test_enum_pickle():
5151
# exercise_trampoline
5252
#
5353
class SimplePyDerived(m.SimpleBase):
54-
pass
54+
def get_value_via_vtable(self):
55+
return 100
56+
5557

5658

5759
def test_roundtrip_simple_py_derived():
5860
p = SimplePyDerived()
5961
p.num = 202
6062
p.stored_in_dict = 303
63+
assert m.get_value_via_vtable_cpp(p) == 100
6164
data = pickle.dumps(p, pickle.HIGHEST_PROTOCOL)
6265
p2 = pickle.loads(data)
6366
assert isinstance(p2, SimplePyDerived)
6467
assert p2.num == 202
6568
assert p2.stored_in_dict == 303
69+
assert m.get_value_via_vtable_cpp(p2) == 100
6670

6771

6872
def test_roundtrip_simple_cpp_derived():
6973
p = m.make_SimpleCppDerivedAsBase()
7074
p.num = 404
75+
assert m.get_value_via_vtable_cpp(p) == 10
7176
if not env.PYPY:
7277
# To ensure that this unit test is not accidentally invalidated.
7378
with pytest.raises(AttributeError):
@@ -77,3 +82,5 @@ def test_roundtrip_simple_cpp_derived():
7782
p2 = pickle.loads(data)
7883
assert isinstance(p2, m.SimpleBase)
7984
assert p2.num == 404
85+
# ERROR: Fails due to object slicing.
86+
assert m.get_value_via_vtable_cpp(p2) == 10

0 commit comments

Comments
 (0)