Skip to content

Commit d588997

Browse files
committed
Adding documentation with associated test: Using py::classh but with fallback to classic pybind11
1 parent 793adbd commit d588997

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

README_smart_holder.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,17 @@ of interest have made the switch, because then the code will continue to
164164
work in either mode.
165165

166166

167+
Using py::classh but with fallback to classic pybind11
168+
------------------------------------------------------
169+
170+
This could be viewed as super-conservative mode, for situations in which
171+
compatibility with classic pybind11 (without smart_holder) is needed for
172+
some period of time. The main idea is to enable use of ``py::classh``
173+
and the associated ``PYBIND11_SMART_HOLDER_TYPE_CASTERS`` macro while
174+
still being able to build the same code with classic pybind11. Please see
175+
tests/test_classh_mock.cpp for an example.
176+
177+
167178
Trampolines and std::unique_ptr
168179
-------------------------------
169180

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ set(PYBIND11_TEST_FILES
112112
test_class_sh_trampoline_unique_ptr.cpp
113113
test_class_sh_unique_ptr_member.cpp
114114
test_class_sh_virtual_py_cpp_mix.cpp
115+
test_classh_mock.cpp
115116
test_constants_and_functions.cpp
116117
test_copy_move.cpp
117118
test_custom_type_casters.cpp

tests/test_classh_mock.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "pybind11_tests.h"
2+
3+
// The main purpose of this test is to ensure the suggested BOILERPLATE code block below is
4+
// correct.
5+
6+
// Copy this block of code into your project.
7+
// Replace FOOEXT with the name of your project.
8+
// BOILERPLATE BEGIN
9+
#ifdef FOOEXT_USING_PYBIND11_SMART_HOLDER
10+
# include <pybind11/smart_holder.h>
11+
#else
12+
# include <pybind11/pybind11.h>
13+
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
14+
template <typename type_, typename... options>
15+
using classh = class_<type_, options...>;
16+
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
17+
# ifndef PYBIND11_SMART_HOLDER_TYPE_CASTERS
18+
# define PYBIND11_SMART_HOLDER_TYPE_CASTERS(...)
19+
# endif
20+
# ifndef PYBIND11_TYPE_CASTER_BASE_HOLDER
21+
# define PYBIND11_TYPE_CASTER_BASE_HOLDER(...)
22+
# endif
23+
#endif
24+
// BOILERPLATE END
25+
26+
namespace {
27+
struct Foo0 {};
28+
struct Foo1 {};
29+
struct Foo2 {};
30+
} // namespace
31+
32+
PYBIND11_TYPE_CASTER_BASE_HOLDER(Foo1, std::shared_ptr<Foo1>)
33+
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Foo2)
34+
35+
TEST_SUBMODULE(classh_mock, m) {
36+
// Uses std::unique_ptr<Foo0> as holder in conservative mode, py::smart_holder in progressive
37+
// mode (if available).
38+
py::class_<Foo0>(m, "Foo0").def(py::init<>());
39+
40+
// Always uses std::shared_ptr<Foo1> as holder.
41+
py::class_<Foo1, std::shared_ptr<Foo1>>(m, "Foo1").def(py::init<>());
42+
43+
// Uses py::smart_holder if available, or std::unique_ptr<Foo2> if only pybind11 classic is
44+
// available.
45+
py::classh<Foo2>(m, "Foo2").def(py::init<>());
46+
}

tests/test_classh_mock.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from pybind11_tests import classh_mock as m
4+
5+
6+
def test_foobar():
7+
# Not really testing anything in particular. The main purpose of this test is to ensure the
8+
# suggested BOILERPLATE code block in test_classh_mock.cpp is correct.
9+
assert m.Foo0()
10+
assert m.Foo1()
11+
assert m.Foo2()

0 commit comments

Comments
 (0)