mirror of
https://github.com/RYDE-WORK/pybind11.git
synced 2026-02-04 22:46:15 +08:00
parent
b0292c1df3
commit
0d765f4a7c
@ -174,6 +174,9 @@ struct type_record {
|
|||||||
/// How large is pybind11::instance<type>?
|
/// How large is pybind11::instance<type>?
|
||||||
size_t instance_size = 0;
|
size_t instance_size = 0;
|
||||||
|
|
||||||
|
/// The global operator new can be overridden with a class-specific variant
|
||||||
|
void *(*operator_new)(size_t) = ::operator new;
|
||||||
|
|
||||||
/// Function pointer to class_<..>::init_holder
|
/// Function pointer to class_<..>::init_holder
|
||||||
void (*init_holder)(PyObject *, const void *) = nullptr;
|
void (*init_holder)(PyObject *, const void *) = nullptr;
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ inline PyTypeObject *make_default_metaclass();
|
|||||||
struct type_info {
|
struct type_info {
|
||||||
PyTypeObject *type;
|
PyTypeObject *type;
|
||||||
size_t type_size;
|
size_t type_size;
|
||||||
|
void *(*operator_new)(size_t);
|
||||||
void (*init_holder)(PyObject *, const void *);
|
void (*init_holder)(PyObject *, const void *);
|
||||||
void (*dealloc)(PyObject *);
|
void (*dealloc)(PyObject *);
|
||||||
std::vector<PyObject *(*)(PyObject *, PyTypeObject *)> implicit_conversions;
|
std::vector<PyObject *(*)(PyObject *, PyTypeObject *)> implicit_conversions;
|
||||||
|
|||||||
@ -183,7 +183,7 @@ extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *,
|
|||||||
PyObject *self = type->tp_alloc(type, 0);
|
PyObject *self = type->tp_alloc(type, 0);
|
||||||
auto instance = (instance_essentials<void> *) self;
|
auto instance = (instance_essentials<void> *) self;
|
||||||
auto tinfo = get_type_info(type);
|
auto tinfo = get_type_info(type);
|
||||||
instance->value = ::operator new(tinfo->type_size);
|
instance->value = tinfo->operator_new(tinfo->type_size);
|
||||||
instance->owned = true;
|
instance->owned = true;
|
||||||
instance->holder_constructed = false;
|
instance->holder_constructed = false;
|
||||||
get_internals().registered_instances.emplace(instance->value, self);
|
get_internals().registered_instances.emplace(instance->value, self);
|
||||||
|
|||||||
@ -427,6 +427,13 @@ template<size_t N> using make_index_sequence = typename make_index_sequence_impl
|
|||||||
template <bool B> using bool_constant = std::integral_constant<bool, B>;
|
template <bool B> using bool_constant = std::integral_constant<bool, B>;
|
||||||
template <typename T> struct negation : bool_constant<!T::value> { };
|
template <typename T> struct negation : bool_constant<!T::value> { };
|
||||||
|
|
||||||
|
#ifdef __cpp_lib_void_t
|
||||||
|
using std::void_t;
|
||||||
|
#else
|
||||||
|
template <typename...> struct void_t_impl { using type = void; };
|
||||||
|
template <typename... Ts> using void_t = typename void_t_impl<Ts...>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Compile-time all/any/none of that check the boolean value of all template types
|
/// Compile-time all/any/none of that check the boolean value of all template types
|
||||||
#ifdef __cpp_fold_expressions
|
#ifdef __cpp_fold_expressions
|
||||||
template <class... Ts> using all_of = bool_constant<(Ts::value && ...)>;
|
template <class... Ts> using all_of = bool_constant<(Ts::value && ...)>;
|
||||||
|
|||||||
@ -803,6 +803,7 @@ protected:
|
|||||||
auto *tinfo = new detail::type_info();
|
auto *tinfo = new detail::type_info();
|
||||||
tinfo->type = (PyTypeObject *) m_ptr;
|
tinfo->type = (PyTypeObject *) m_ptr;
|
||||||
tinfo->type_size = rec.type_size;
|
tinfo->type_size = rec.type_size;
|
||||||
|
tinfo->operator_new = rec.operator_new;
|
||||||
tinfo->init_holder = rec.init_holder;
|
tinfo->init_holder = rec.init_holder;
|
||||||
tinfo->dealloc = rec.dealloc;
|
tinfo->dealloc = rec.dealloc;
|
||||||
|
|
||||||
@ -860,6 +861,18 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Set the pointer to operator new if it exists. The cast is needed because it can be overloaded.
|
||||||
|
template <typename T, typename = void_t<decltype(static_cast<void *(*)(size_t)>(T::operator new))>>
|
||||||
|
void set_operator_new(type_record *r) { r->operator_new = &T::operator new; }
|
||||||
|
|
||||||
|
template <typename> void set_operator_new(...) { }
|
||||||
|
|
||||||
|
/// Call class-specific delete if it exists or global otherwise. Can also be an overload set.
|
||||||
|
template <typename T, typename = void_t<decltype(static_cast<void (*)(void *)>(T::operator delete))>>
|
||||||
|
void call_operator_delete(T *p) { T::operator delete(p); }
|
||||||
|
|
||||||
|
inline void call_operator_delete(void *p) { ::operator delete(p); }
|
||||||
|
|
||||||
NAMESPACE_END(detail)
|
NAMESPACE_END(detail)
|
||||||
|
|
||||||
template <typename type_, typename... options>
|
template <typename type_, typename... options>
|
||||||
@ -905,6 +918,8 @@ public:
|
|||||||
record.dealloc = dealloc;
|
record.dealloc = dealloc;
|
||||||
record.default_holder = std::is_same<holder_type, std::unique_ptr<type>>::value;
|
record.default_holder = std::is_same<holder_type, std::unique_ptr<type>>::value;
|
||||||
|
|
||||||
|
set_operator_new<type>(&record);
|
||||||
|
|
||||||
/* Register base classes specified via template arguments to class_, if any */
|
/* Register base classes specified via template arguments to class_, if any */
|
||||||
bool unused[] = { (add_base<options>(record), false)..., false };
|
bool unused[] = { (add_base<options>(record), false)..., false };
|
||||||
(void) unused;
|
(void) unused;
|
||||||
@ -1125,7 +1140,7 @@ private:
|
|||||||
if (inst->holder_constructed)
|
if (inst->holder_constructed)
|
||||||
inst->holder.~holder_type();
|
inst->holder.~holder_type();
|
||||||
else if (inst->owned)
|
else if (inst->owned)
|
||||||
::operator delete(inst->value);
|
detail::call_operator_delete(inst->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static detail::function_record *get_function_record(handle h) {
|
static detail::function_record *get_function_record(handle h) {
|
||||||
|
|||||||
@ -60,6 +60,15 @@ template <typename MatrixArgType> Eigen::MatrixXd adjust_matrix(MatrixArgType m)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CustomOperatorNew {
|
||||||
|
CustomOperatorNew() = default;
|
||||||
|
|
||||||
|
Eigen::Matrix4d a = Eigen::Matrix4d::Zero();
|
||||||
|
Eigen::Matrix4d b = Eigen::Matrix4d::Identity();
|
||||||
|
|
||||||
|
EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
|
||||||
|
};
|
||||||
|
|
||||||
test_initializer eigen([](py::module &m) {
|
test_initializer eigen([](py::module &m) {
|
||||||
typedef Eigen::Matrix<float, 5, 6, Eigen::RowMajor> FixedMatrixR;
|
typedef Eigen::Matrix<float, 5, 6, Eigen::RowMajor> FixedMatrixR;
|
||||||
typedef Eigen::Matrix<float, 5, 6> FixedMatrixC;
|
typedef Eigen::Matrix<float, 5, 6> FixedMatrixC;
|
||||||
@ -277,4 +286,9 @@ test_initializer eigen([](py::module &m) {
|
|||||||
// requiring a copy!) because the stride value can be safely ignored on a size-1 dimension.
|
// requiring a copy!) because the stride value can be safely ignored on a size-1 dimension.
|
||||||
m.def("iss738_f1", &adjust_matrix<const Eigen::Ref<const Eigen::MatrixXd> &>, py::arg().noconvert());
|
m.def("iss738_f1", &adjust_matrix<const Eigen::Ref<const Eigen::MatrixXd> &>, py::arg().noconvert());
|
||||||
m.def("iss738_f2", &adjust_matrix<const Eigen::Ref<const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>> &>, py::arg().noconvert());
|
m.def("iss738_f2", &adjust_matrix<const Eigen::Ref<const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>> &>, py::arg().noconvert());
|
||||||
|
|
||||||
|
py::class_<CustomOperatorNew>(m, "CustomOperatorNew")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def_readonly("a", &CustomOperatorNew::a)
|
||||||
|
.def_readonly("b", &CustomOperatorNew::b);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -614,3 +614,13 @@ def test_issue738():
|
|||||||
|
|
||||||
assert np.all(iss738_f2(np.array([[1., 2, 3]])) == np.array([[1., 102, 203]]))
|
assert np.all(iss738_f2(np.array([[1., 2, 3]])) == np.array([[1., 102, 203]]))
|
||||||
assert np.all(iss738_f2(np.array([[1.], [2], [3]])) == np.array([[1.], [12], [23]]))
|
assert np.all(iss738_f2(np.array([[1.], [2], [3]])) == np.array([[1.], [12], [23]]))
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_operator_new():
|
||||||
|
"""Using Eigen types as member variables requires a class-specific
|
||||||
|
operator new with proper alignment"""
|
||||||
|
from pybind11_tests import CustomOperatorNew
|
||||||
|
|
||||||
|
o = CustomOperatorNew()
|
||||||
|
np.testing.assert_allclose(o.a, 0.0)
|
||||||
|
np.testing.assert_allclose(o.b.diagonal(), 1.0)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user