pybind11 icon indicating copy to clipboard operation
pybind11 copied to clipboard

py::cast variant using type_info instead of template argument for non-virtual types.

Open 2bam opened this issue 8 years ago • 1 comments

Issue description

It would be a nice feature to have a non-template casting function using type_info for non-virtual types. I gather pybind11 for static-types binds the type_info to the first export of the type by ptr (if it was a Base it gets locked in Base, if it was a Derived stays a Derived, etc)

I made a workaround by accessing the detail part of pybind, so I guess it could change eventually.

Use case

In C++ I have dynamic-bound factories wrappers like Base *Create( int id ) T *Create<T>() { return static_cast<T*>(Create( id_map[typeid(T)] )); }.

To avoid having to make one py-binding for each type (non-scalable), I export a py::object Create(int id) that changes the return type according to a type_info.

Setup

pybind11 2.2.1

Example code

DIRECT TYPE

py::object castComponentByTypeInfo(Base *src, const std::type_info &type) {
	using T1 = pybind11::detail::type_caster_generic;

	auto &st = T1::src_and_type(src, type, nullptr);
	assert(st.second != nullptr);

	auto handle = T1::cast(
		st.first, py::return_value_policy::reference, {}, st.second,
		nullptr, nullptr
	);
	return py::reinterpret_borrow<py::object>(handle);
}

HELD TYPE

py::object castComponentByTypeInfo(holder<Base> src, const std::type_info &type) {
	using T1 = pybind11::detail::type_caster_generic;

	auto &st = T1::src_and_type(src.get(), type, nullptr);
	assert(st.second != nullptr);

	auto handle = T1::cast(
		st.first, py::return_value_policy::take_ownership, {}, st.second,
		nullptr, nullptr, &src);

	return py::reinterpret_steal<py::object>(handle);
}

2bam avatar Oct 26 '17 19:10 2bam