mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 16:13:53 +00:00
moving prototype code to pybind11/vptr_holder.h, adding type_caster specialization to make the bindings involving unique_ptr passing compile, but load and cast implementations are missing
This commit is contained in:
parent
d2c8e3ccde
commit
ea1cdf82ce
72
include/pybind11/vptr_holder.h
Normal file
72
include/pybind11/vptr_holder.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
// Could this be a holder for a `class_`-like `vclass`?
|
||||||
|
// To enable passing of unique_ptr as in pure C++.
|
||||||
|
template <typename T> class vptr {
|
||||||
|
public:
|
||||||
|
explicit vptr(T *ptr = nullptr) : vptr_{std::unique_ptr<T>(ptr)} {}
|
||||||
|
explicit vptr(std::unique_ptr<T> u) : vptr_{std::move(u)} {}
|
||||||
|
explicit vptr(std::shared_ptr<T> s) : vptr_{s} {}
|
||||||
|
|
||||||
|
int ownership_type() const {
|
||||||
|
if (std::get_if<0>(&vptr_)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (std::get_if<1>(&vptr_)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
T *get() {
|
||||||
|
auto u = std::get_if<0>(&vptr_);
|
||||||
|
if (u) {
|
||||||
|
return u->get();
|
||||||
|
}
|
||||||
|
auto s = std::get_if<1>(&vptr_);
|
||||||
|
if (s) {
|
||||||
|
return s->get();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<T> get_unique() {
|
||||||
|
auto u = std::get_if<0>(&vptr_);
|
||||||
|
if (u) {
|
||||||
|
return std::move(*u);
|
||||||
|
}
|
||||||
|
throw std::runtime_error("get_unique failure.");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<T> get_shared() {
|
||||||
|
auto s = std::get_if<1>(&vptr_);
|
||||||
|
if (s) {
|
||||||
|
return *s;
|
||||||
|
}
|
||||||
|
auto u = std::get_if<0>(&vptr_);
|
||||||
|
if (u) {
|
||||||
|
auto result = std::shared_ptr<T>(std::move(*u));
|
||||||
|
vptr_ = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("get_shared failure.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::variant<std::unique_ptr<T>, std::shared_ptr<T>> vptr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> class vptr_holder : public vptr<T> {
|
||||||
|
using vptr<T>::vptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
PYBIND11_DECLARE_HOLDER_TYPE(T, pybind11::vptr_holder<T>);
|
@ -1,5 +1,7 @@
|
|||||||
#include "pybind11_tests.h"
|
#include "pybind11_tests.h"
|
||||||
|
|
||||||
|
#include <pybind11/vptr_holder.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -66,17 +68,46 @@ inline int cpp_pattern() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace unique_ptr_member
|
||||||
|
} // namespace pybind11_tests
|
||||||
|
|
||||||
|
namespace pybind11 {
|
||||||
|
namespace detail {
|
||||||
|
template <>
|
||||||
|
struct type_caster<
|
||||||
|
std::unique_ptr<pybind11_tests::unique_ptr_member::pointee>> {
|
||||||
|
public:
|
||||||
|
PYBIND11_TYPE_CASTER(
|
||||||
|
std::unique_ptr<pybind11_tests::unique_ptr_member::pointee>,
|
||||||
|
_("std::unique_ptr<pybind11_tests::unique_ptr_member::pointee>"));
|
||||||
|
|
||||||
|
bool load(handle /* src */, bool) {
|
||||||
|
throw std::runtime_error("Not implemented: load");
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle
|
||||||
|
cast(std::unique_ptr<pybind11_tests::unique_ptr_member::pointee> /* src */,
|
||||||
|
return_value_policy /* policy */, handle /* parent */) {
|
||||||
|
throw std::runtime_error("Not implemented: cast");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace pybind11
|
||||||
|
|
||||||
|
namespace pybind11_tests {
|
||||||
|
namespace unique_ptr_member {
|
||||||
|
|
||||||
TEST_SUBMODULE(unique_ptr_member, m) {
|
TEST_SUBMODULE(unique_ptr_member, m) {
|
||||||
m.def("to_cout", to_cout);
|
m.def("to_cout", to_cout);
|
||||||
|
|
||||||
py::class_<pointee, std::shared_ptr<pointee>>(m, "pointee")
|
py::class_<pointee, py::vptr_holder<pointee>>(m, "pointee")
|
||||||
.def(py::init<>())
|
.def(py::init<>())
|
||||||
.def("get_int", &pointee::get_int);
|
.def("get_int", &pointee::get_int);
|
||||||
|
|
||||||
m.def("make_unique_pointee", make_unique_pointee);
|
m.def("make_unique_pointee", make_unique_pointee);
|
||||||
|
|
||||||
py::class_<ptr_owner>(m, "ptr_owner")
|
py::class_<ptr_owner>(m, "ptr_owner")
|
||||||
//.def(py::init<std::unique_ptr<pointee>>(), py::arg("ptr"))
|
.def(py::init<std::unique_ptr<pointee>>(), py::arg("ptr"))
|
||||||
.def("is_owner", &ptr_owner::is_owner)
|
.def("is_owner", &ptr_owner::is_owner)
|
||||||
.def("give_up_ownership_via_unique_ptr",
|
.def("give_up_ownership_via_unique_ptr",
|
||||||
&ptr_owner::give_up_ownership_via_unique_ptr)
|
&ptr_owner::give_up_ownership_via_unique_ptr)
|
||||||
|
@ -1,74 +1,22 @@
|
|||||||
|
#include "pybind11_tests.h"
|
||||||
|
|
||||||
|
#include <pybind11/vptr_holder.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
#include "pybind11_tests.h"
|
|
||||||
|
|
||||||
namespace pybind11_tests {
|
namespace pybind11_tests {
|
||||||
|
|
||||||
// Could this be a holder for a `class_`-like `vclass`?
|
using pybind11::vptr;
|
||||||
// To enable passing of unique_ptr as in pure C++.
|
|
||||||
template <typename T> class vptr_holder {
|
|
||||||
public:
|
|
||||||
explicit vptr_holder(T *ptr = nullptr) : vptr_{std::unique_ptr<T>(ptr)} {}
|
|
||||||
explicit vptr_holder(std::unique_ptr<T> u) : vptr_{std::move(u)} {}
|
|
||||||
explicit vptr_holder(std::shared_ptr<T> s) : vptr_{s} {}
|
|
||||||
|
|
||||||
int ownership_type() const {
|
vptr<double> from_raw() { return vptr<double>{new double{3}}; }
|
||||||
if (std::get_if<0>(&vptr_)) {
|
|
||||||
return 0;
|
vptr<double> from_unique() {
|
||||||
}
|
return vptr<double>{std::unique_ptr<double>(new double{5})};
|
||||||
if (std::get_if<1>(&vptr_)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
T *get() {
|
vptr<double> from_shared() {
|
||||||
auto u = std::get_if<0>(&vptr_);
|
return vptr<double>{std::shared_ptr<double>(new double{7})};
|
||||||
if (u) {
|
|
||||||
return u->get();
|
|
||||||
}
|
|
||||||
auto s = std::get_if<1>(&vptr_);
|
|
||||||
if (s) {
|
|
||||||
return s->get();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<T> get_unique() {
|
|
||||||
auto u = std::get_if<0>(&vptr_);
|
|
||||||
if (u) {
|
|
||||||
return std::move(*u);
|
|
||||||
}
|
|
||||||
throw std::runtime_error("get_unique failure.");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<T> get_shared() {
|
|
||||||
auto s = std::get_if<1>(&vptr_);
|
|
||||||
if (s) {
|
|
||||||
return *s;
|
|
||||||
}
|
|
||||||
auto u = std::get_if<0>(&vptr_);
|
|
||||||
if (u) {
|
|
||||||
auto result = std::shared_ptr<T>(std::move(*u));
|
|
||||||
vptr_ = result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
throw std::runtime_error("get_shared failure.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::variant<std::unique_ptr<T>, std::shared_ptr<T>> vptr_;
|
|
||||||
};
|
|
||||||
|
|
||||||
vptr_holder<double> from_raw() { return vptr_holder<double>{new double{3}}; }
|
|
||||||
|
|
||||||
vptr_holder<double> from_unique() {
|
|
||||||
return vptr_holder<double>{std::unique_ptr<double>(new double{5})};
|
|
||||||
}
|
|
||||||
|
|
||||||
vptr_holder<double> from_shared() {
|
|
||||||
return vptr_holder<double>{std::shared_ptr<double>(new double{7})};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_SUBMODULE(variant_unique_shared, m) {
|
TEST_SUBMODULE(variant_unique_shared, m) {
|
||||||
@ -77,22 +25,22 @@ TEST_SUBMODULE(variant_unique_shared, m) {
|
|||||||
m.def("from_unique", from_unique);
|
m.def("from_unique", from_unique);
|
||||||
m.def("from_shared", from_shared);
|
m.def("from_shared", from_shared);
|
||||||
|
|
||||||
py::class_<vptr_holder<double>>(m, "vptr_holder_double")
|
py::class_<vptr<double>>(m, "vptr_double")
|
||||||
.def(py::init<>())
|
.def(py::init<>())
|
||||||
.def("ownership_type", &vptr_holder<double>::ownership_type)
|
.def("ownership_type", &vptr<double>::ownership_type)
|
||||||
.def("get_value",
|
.def("get_value",
|
||||||
[](vptr_holder<double> &v) {
|
[](vptr<double> &v) {
|
||||||
auto p = v.get();
|
auto p = v.get();
|
||||||
if (p)
|
if (p)
|
||||||
return *p;
|
return *p;
|
||||||
return -1.;
|
return -1.;
|
||||||
})
|
})
|
||||||
.def("get_unique",
|
.def("get_unique",
|
||||||
[](vptr_holder<double> &v) {
|
[](vptr<double> &v) {
|
||||||
v.get_unique();
|
v.get_unique();
|
||||||
return;
|
return;
|
||||||
})
|
})
|
||||||
.def("get_shared", [](vptr_holder<double> &v) {
|
.def("get_shared", [](vptr<double> &v) {
|
||||||
v.get_shared();
|
v.get_shared();
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@ from pybind11_tests import variant_unique_shared as m
|
|||||||
|
|
||||||
|
|
||||||
def test_default_constructed():
|
def test_default_constructed():
|
||||||
v = m.vptr_holder_double()
|
v = m.vptr_double()
|
||||||
assert v.ownership_type() == 0
|
assert v.ownership_type() == 0
|
||||||
assert v.get_value() == -1
|
assert v.get_value() == -1
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user