-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Add pybind11_select_caster
#3862
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
7dd6396
93f1577
47eab84
cb9fe3e
62bb9df
0f17bae
7924f18
a29e352
8e8ac55
910a4aa
4fc1ddc
974b029
9043841
06571a4
38fdea3
a48f5cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// adl = Argument Dependent Lookup | ||
|
||
#include "pybind11_tests.h" | ||
|
||
namespace have_a_ns { | ||
struct type_mock {}; | ||
struct mock_caster { | ||
static int num() { return 101; } | ||
}; | ||
mock_caster pybind11_select_caster(type_mock *); | ||
} // namespace have_a_ns | ||
|
||
// namespace global { | ||
struct global_ns_type_mock {}; | ||
struct global_ns_mock_caster { | ||
static int num() { return 202; } | ||
}; | ||
global_ns_mock_caster pybind11_select_caster(global_ns_type_mock *); | ||
// } // namespace global | ||
|
||
namespace { | ||
struct unnamed_ns_type_mock {}; | ||
struct unnamed_ns_mock_caster { | ||
static int num() { return 303; } | ||
}; | ||
unnamed_ns_mock_caster pybind11_select_caster(unnamed_ns_type_mock *); | ||
#if !defined(_MSC_VER) | ||
// Dummy implementation, purely to avoid compiler warnings (unused function). | ||
// Easier than managing compiler-specific pragmas for warning suppression. | ||
// MSVC happens to not generate any warnings. Leveraging that to prove that | ||
// this test actually works without an implementation. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe mention There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestion! We already have |
||
unnamed_ns_mock_caster pybind11_select_caster(unnamed_ns_type_mock *) { | ||
return unnamed_ns_mock_caster{}; | ||
} | ||
#endif | ||
} // namespace | ||
|
||
namespace mrc_ns { // minimal real caster | ||
|
||
struct type_mrc { | ||
int value = -9999; | ||
}; | ||
|
||
struct minimal_real_caster { | ||
static constexpr auto name = py::detail::const_name<type_mrc>(); | ||
|
||
static py::handle | ||
cast(type_mrc const &src, py::return_value_policy /*policy*/, py::handle /*parent*/) { | ||
return py::int_(src.value + 1000).release(); | ||
} | ||
|
||
// Maximizing simplicity. This will go terribly wrong for other arg types. | ||
template <typename> | ||
using cast_op_type = const type_mrc &; | ||
|
||
// NOLINTNEXTLINE(google-explicit-constructor) | ||
operator type_mrc const &() { | ||
static type_mrc obj; | ||
obj.value = 404; | ||
return obj; | ||
} | ||
|
||
bool load(py::handle src, bool /*convert*/) { | ||
// Only accepts str, but the value is ignored. | ||
return py::isinstance<py::str>(src); | ||
} | ||
}; | ||
|
||
minimal_real_caster pybind11_select_caster(type_mrc *); | ||
|
||
} // namespace mrc_ns | ||
|
||
TEST_SUBMODULE(make_caster_adl, m) { | ||
m.def("have_a_ns_num", []() { return py::detail::make_caster<have_a_ns::type_mock>::num(); }); | ||
m.def("global_ns_num", []() { return py::detail::make_caster<global_ns_type_mock>::num(); }); | ||
m.def("unnamed_ns_num", []() { return py::detail::make_caster<unnamed_ns_type_mock>::num(); }); | ||
|
||
m.def("mrc_return", []() { | ||
mrc_ns::type_mrc obj; | ||
obj.value = 505; | ||
return obj; | ||
}); | ||
m.def("mrc_arg", [](mrc_ns::type_mrc const &obj) { return obj.value + 2000; }); | ||
|
||
#if !defined(_MSC_VER) | ||
// Dummy call, purely to avoid compiler warnings (unused function). | ||
(void) pybind11_select_caster(static_cast<unnamed_ns_type_mock *>(nullptr)); | ||
#endif | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# -*- coding: utf-8 -*- | ||
import pytest | ||
|
||
from pybind11_tests import make_caster_adl as m | ||
from pybind11_tests import make_caster_adl_alt as m_alt | ||
|
||
|
||
def test_mock_casters(): | ||
assert m.have_a_ns_num() == 101 | ||
assert m.global_ns_num() == 202 | ||
assert m.unnamed_ns_num() == 303 | ||
|
||
|
||
def test_mock_casters_alt(): | ||
assert m_alt.have_a_ns_num() == 121 | ||
|
||
|
||
def test_minimal_real_caster(): | ||
assert m.mrc_return() == 1505 | ||
assert m.mrc_arg(u"ignored") == 2404 | ||
with pytest.raises(TypeError) as excinfo: | ||
m.mrc_arg(None) | ||
assert "(arg0: mrc_ns::type_mrc) -> int" in str(excinfo.value) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#include "pybind11_tests.h" | ||
|
||
namespace have_a_ns { | ||
struct type_mock {}; | ||
struct mock_caster_alt { | ||
static int num() { return 121; } | ||
}; | ||
mock_caster_alt pybind11_select_caster(type_mock *); | ||
} // namespace have_a_ns | ||
|
||
TEST_SUBMODULE(make_caster_adl_alt, m) { | ||
m.def("have_a_ns_num", []() { return py::detail::make_caster<have_a_ns::type_mock>::num(); }); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from pybind11_tests import make_caster_adl_alt as m | ||
|
||
|
||
def test_mock_casters(): | ||
assert m.have_a_ns_num() == 121 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: This is actually a bad practice in our documentation. We should clear the python error or raise it to a C++ error if it makes sense Leaving the error state like this not ideal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be a good followup, unless you want to suggest the update inline. It might be elsewhere?