Skip to content

[smart_holder] Implement try_as_void_ptr_capsule as a free function #4539

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

Merged
merged 2 commits into from
Mar 1, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 34 additions & 22 deletions include/pybind11/detail/smart_holder_type_casters.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,37 @@ struct is_smart_holder_type<smart_holder> : std::true_type {};
inline void register_instance(instance *self, void *valptr, const type_info *tinfo);
inline bool deregister_instance(instance *self, void *valptr, const type_info *tinfo);

// Replace all occurrences of a character in string.
inline void replace_all(std::string &str, const std::string &from, char to) {
size_t pos = str.find(from);
while (pos != std::string::npos) {
str.replace(pos, from.length(), 1, to);
pos = str.find(from, pos);
// Replace all occurrences of substrings in a string.
inline void replace_all(std::string &str, const std::string &from, const std::string &to) {
if (str.empty()) {
return;
}
size_t pos = 0;
while ((pos = str.find(from, pos)) != std::string::npos) {
str.replace(pos, from.length(), to);
pos += to.length();
}
}

inline void *try_as_void_ptr_capsule_get_pointer(handle src, const char *typeid_name) {
std::string type_name = typeid_name;
detail::clean_type_id(type_name);

// Convert `a::b::c` to `a_b_c`.
replace_all(type_name, "::", "_");
// Remove all `*` in the type name.
replace_all(type_name, "*", "");

std::string as_void_ptr_function_name("as_");
as_void_ptr_function_name += type_name;
if (hasattr(src, as_void_ptr_function_name.c_str())) {
auto as_void_ptr_function = function(src.attr(as_void_ptr_function_name.c_str()));
auto void_ptr_capsule = as_void_ptr_function();
if (isinstance<capsule>(void_ptr_capsule)) {
return reinterpret_borrow<capsule>(void_ptr_capsule).get_pointer();
}
}
return nullptr;
}

// The modified_type_caster_generic_load_impl could replace type_caster_generic::load_impl but not
Expand Down Expand Up @@ -120,22 +144,10 @@ class modified_type_caster_generic_load_impl {
}

bool try_as_void_ptr_capsule(handle src) {
std::string type_name = cpptype->name();
detail::clean_type_id(type_name);

// Convert `a::b::c` to `a_b_c`
replace_all(type_name, "::", '_');

std::string as_void_ptr_function_name("as_");
as_void_ptr_function_name += type_name;
if (hasattr(src, as_void_ptr_function_name.c_str())) {
auto as_void_ptr_function = function(src.attr(as_void_ptr_function_name.c_str()));
auto void_ptr_capsule = as_void_ptr_function();
if (isinstance<capsule>(void_ptr_capsule)) {
unowned_void_ptr_from_void_ptr_capsule
= reinterpret_borrow<capsule>(void_ptr_capsule).get_pointer();
return true;
}
unowned_void_ptr_from_void_ptr_capsule
= try_as_void_ptr_capsule_get_pointer(src, cpptype->name());
if (unowned_void_ptr_from_void_ptr_capsule != nullptr) {
return true;
}
return false;
}
Expand Down