mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 22:52:01 +00:00
cast: Qualify symbol usage in PYBIND11_TYPE_CASTER (#3758)
* cast: Qualify symbol usage in PYBIND11_TYPE_CASTER Permits using macro outside of pybind11::detail * fixup! review
This commit is contained in:
parent
da15bb206c
commit
f495dfc433
@ -85,11 +85,15 @@ protected:
|
|||||||
\
|
\
|
||||||
public: \
|
public: \
|
||||||
static constexpr auto name = py_name; \
|
static constexpr auto name = py_name; \
|
||||||
template <typename T_, enable_if_t<std::is_same<type, remove_cv_t<T_>>::value, int> = 0> \
|
template <typename T_, \
|
||||||
static handle cast(T_ *src, return_value_policy policy, handle parent) { \
|
::pybind11::detail::enable_if_t< \
|
||||||
|
std::is_same<type, ::pybind11::detail::remove_cv_t<T_>>::value, \
|
||||||
|
int> = 0> \
|
||||||
|
static ::pybind11::handle cast( \
|
||||||
|
T_ *src, ::pybind11::return_value_policy policy, ::pybind11::handle parent) { \
|
||||||
if (!src) \
|
if (!src) \
|
||||||
return none().release(); \
|
return ::pybind11::none().release(); \
|
||||||
if (policy == return_value_policy::take_ownership) { \
|
if (policy == ::pybind11::return_value_policy::take_ownership) { \
|
||||||
auto h = cast(std::move(*src), policy, parent); \
|
auto h = cast(std::move(*src), policy, parent); \
|
||||||
delete src; \
|
delete src; \
|
||||||
return h; \
|
return h; \
|
||||||
@ -100,7 +104,7 @@ public:
|
|||||||
operator type &() { return value; } /* NOLINT(bugprone-macro-parentheses) */ \
|
operator type &() { return value; } /* NOLINT(bugprone-macro-parentheses) */ \
|
||||||
operator type &&() && { return std::move(value); } /* NOLINT(bugprone-macro-parentheses) */ \
|
operator type &&() && { return std::move(value); } /* NOLINT(bugprone-macro-parentheses) */ \
|
||||||
template <typename T_> \
|
template <typename T_> \
|
||||||
using cast_op_type = pybind11::detail::movable_cast_op_type<T_>
|
using cast_op_type = ::pybind11::detail::movable_cast_op_type<T_>
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
using is_std_char_type = any_of<std::is_same<CharT, char>, /* std::string */
|
using is_std_char_type = any_of<std::is_same<CharT, char>, /* std::string */
|
||||||
|
@ -20,6 +20,7 @@ public:
|
|||||||
std::string arg = "(default arg inspector 2)";
|
std::string arg = "(default arg inspector 2)";
|
||||||
};
|
};
|
||||||
class ArgAlwaysConverts {};
|
class ArgAlwaysConverts {};
|
||||||
|
|
||||||
namespace pybind11 {
|
namespace pybind11 {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <>
|
template <>
|
||||||
@ -105,6 +106,34 @@ struct type_caster<DestructionTester> {
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace pybind11
|
} // namespace pybind11
|
||||||
|
|
||||||
|
// Define type caster outside of `pybind11::detail` and then alias it.
|
||||||
|
namespace other_lib {
|
||||||
|
struct MyType {};
|
||||||
|
// Corrupt `py` shorthand alias for surrounding context.
|
||||||
|
namespace py {}
|
||||||
|
// Corrupt unqualified relative `pybind11` namespace.
|
||||||
|
namespace pybind11 {}
|
||||||
|
// Correct alias.
|
||||||
|
namespace py_ = ::pybind11;
|
||||||
|
// Define caster. This is effectively no-op, we only ensure it compiles and we
|
||||||
|
// don't have any symbol collision when using macro mixin.
|
||||||
|
struct my_caster {
|
||||||
|
PYBIND11_TYPE_CASTER(MyType, py_::detail::const_name("MyType"));
|
||||||
|
bool load(py_::handle, bool) { return true; }
|
||||||
|
|
||||||
|
static py_::handle cast(const MyType &, py_::return_value_policy, py_::handle) {
|
||||||
|
return py_::bool_(true).release();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace other_lib
|
||||||
|
// Effectively "alias" it into correct namespace (via inheritance).
|
||||||
|
namespace pybind11 {
|
||||||
|
namespace detail {
|
||||||
|
template <>
|
||||||
|
struct type_caster<other_lib::MyType> : public other_lib::my_caster {};
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace pybind11
|
||||||
|
|
||||||
TEST_SUBMODULE(custom_type_casters, m) {
|
TEST_SUBMODULE(custom_type_casters, m) {
|
||||||
// test_custom_type_casters
|
// test_custom_type_casters
|
||||||
|
|
||||||
@ -175,4 +204,6 @@ TEST_SUBMODULE(custom_type_casters, m) {
|
|||||||
m.def("destruction_tester_cstats",
|
m.def("destruction_tester_cstats",
|
||||||
&ConstructorStats::get<DestructionTester>,
|
&ConstructorStats::get<DestructionTester>,
|
||||||
py::return_value_policy::reference);
|
py::return_value_policy::reference);
|
||||||
|
|
||||||
|
m.def("other_lib_type", [](other_lib::MyType x) { return x; });
|
||||||
}
|
}
|
||||||
|
@ -114,3 +114,7 @@ def test_custom_caster_destruction():
|
|||||||
|
|
||||||
# Make sure we still only have the original object (from ..._no_destroy()) alive:
|
# Make sure we still only have the original object (from ..._no_destroy()) alive:
|
||||||
assert cstats.alive() == 1
|
assert cstats.alive() == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_caster_other_lib():
|
||||||
|
assert m.other_lib_type(True)
|
||||||
|
Loading…
Reference in New Issue
Block a user