mirror of
https://github.com/pybind/pybind11.git
synced 2024-12-01 17:37:15 +00:00
Snapshot of WIP, TODO: shared_ptr deleter with on/off switch
This commit is contained in:
parent
76e99f1c81
commit
72d1b61176
75
include/pybind11/smart_holder_poc.h
Normal file
75
include/pybind11/smart_holder_poc.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
struct smart_holder {
|
||||||
|
std::shared_ptr<void> vptr;
|
||||||
|
const std::type_info* rtti_held;
|
||||||
|
const std::type_info* rtti_uqp_del;
|
||||||
|
bool have_external_shp;
|
||||||
|
|
||||||
|
smart_holder()
|
||||||
|
: rtti_held{nullptr}, rtti_uqp_del{nullptr}, have_external_shp(false) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void ensure_compatible_rtti(const char* context) {
|
||||||
|
const std::type_info* rtti_requested = &typeid(T);
|
||||||
|
if (!(*rtti_requested == *rtti_held)) {
|
||||||
|
throw std::runtime_error(std::string("Incompatible RTTI (") + context +
|
||||||
|
").");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensure_use_count_1(const char* context) {
|
||||||
|
if (vptr.use_count() != 1) {
|
||||||
|
throw std::runtime_error(std::string("Cannot disown use_count != 1 (") +
|
||||||
|
context + ").");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensure_unique_ptr_default_deleter(const char* context) {
|
||||||
|
if (rtti_uqp_del != nullptr) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
std::string("Cannot disown unique_ptr deleter (") + context + ").");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensure_internal_shared_ptr(const char* context) {
|
||||||
|
if (have_external_shp) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
std::string("Cannot disown external shared_ptr (") + context + ").");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void from_raw_ptr_owned(T* raw_ptr) {
|
||||||
|
vptr.reset(raw_ptr);
|
||||||
|
rtti_held = &typeid(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* as_raw_ptr_owned() {
|
||||||
|
static const char* context = "as_raw_ptr_owned";
|
||||||
|
ensure_compatible_rtti<T>(context);
|
||||||
|
ensure_use_count_1(context);
|
||||||
|
ensure_unique_ptr_default_deleter(context);
|
||||||
|
ensure_internal_shared_ptr(context);
|
||||||
|
std::shared_ptr<T> tptr = std::static_pointer_cast<T>(vptr);
|
||||||
|
vptr.reset();
|
||||||
|
T* result = tptr.get();
|
||||||
|
// TODO tptr.release();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::shared_ptr<T> as_shared_ptr() {
|
||||||
|
static const char* context = "as_shared_ptr";
|
||||||
|
ensure_compatible_rtti<T>(context);
|
||||||
|
return std::static_pointer_cast<T>(vptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
32
tests/test_smart_holder_poc.cpp
Normal file
32
tests/test_smart_holder_poc.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "pybind11_tests.h"
|
||||||
|
|
||||||
|
#include <pybind11/smart_holder_poc.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace pybind11_tests {
|
||||||
|
namespace smart_holder_poc {
|
||||||
|
|
||||||
|
inline void to_cout(std::string msg) { std::cout << msg << std::endl; }
|
||||||
|
|
||||||
|
inline void exercise() {
|
||||||
|
to_cout("");
|
||||||
|
namespace py = pybind11;
|
||||||
|
py::smart_holder hld;
|
||||||
|
hld.from_raw_ptr_owned(new int(13));
|
||||||
|
to_cout(hld.rtti_held->name());
|
||||||
|
{
|
||||||
|
std::shared_ptr<int> val = hld.as_shared_ptr<int>();
|
||||||
|
to_cout(std::to_string(*val));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::unique_ptr<int> val(hld.as_raw_ptr_owned<int>());
|
||||||
|
to_cout(std::to_string(*val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_SUBMODULE(smart_holder_poc, m) { m.def("exercise", exercise); }
|
||||||
|
|
||||||
|
} // namespace smart_holder_poc
|
||||||
|
} // namespace pybind11_tests
|
8
tests/test_smart_holder_poc.py
Normal file
8
tests/test_smart_holder_poc.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from pybind11_tests import smart_holder_poc as m
|
||||||
|
|
||||||
|
|
||||||
|
def test_exercise():
|
||||||
|
m.exercise()
|
Loading…
Reference in New Issue
Block a user