mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 14:45:12 +00:00
parent
4c5404421f
commit
6898679270
@ -1313,6 +1313,30 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
/// Binds an existing constructor taking arguments Args...
|
||||
template <typename... Args> detail::initimpl::constructor<Args...> init() { return {}; }
|
||||
/// Like `init<Args...>()`, but the instance is always constructed through the alias class (even
|
||||
/// when not inheriting on the Python side).
|
||||
template <typename... Args> detail::initimpl::alias_constructor<Args...> init_alias() { return {}; }
|
||||
|
||||
/// Binds a factory function as a constructor
|
||||
template <typename Func, typename Ret = detail::initimpl::factory<Func>>
|
||||
Ret init(Func &&f) { return {std::forward<Func>(f)}; }
|
||||
|
||||
/// Dual-argument factory function: the first function is called when no alias is needed, the second
|
||||
/// when an alias is needed (i.e. due to python-side inheritance). Arguments must be identical.
|
||||
template <typename CFunc, typename AFunc, typename Ret = detail::initimpl::factory<CFunc, AFunc>>
|
||||
Ret init(CFunc &&c, AFunc &&a) {
|
||||
return {std::forward<CFunc>(c), std::forward<AFunc>(a)};
|
||||
}
|
||||
|
||||
/// Binds pickling functions `__getstate__` and `__setstate__` and ensures that the type
|
||||
/// returned by `__getstate__` is the same as the argument accepted by `__setstate__`.
|
||||
template <typename GetState, typename SetState>
|
||||
detail::initimpl::pickle_factory<GetState, SetState> pickle(GetState &&g, SetState &&s) {
|
||||
return {std::forward<GetState>(g), std::forward<SetState>(s)};
|
||||
};
|
||||
|
||||
/// Binds C++ enumerations and enumeration classes to Python
|
||||
template <typename Type> class enum_ : public class_<Type> {
|
||||
public:
|
||||
@ -1340,7 +1364,7 @@ public:
|
||||
m[kv.first] = kv.second;
|
||||
return m;
|
||||
}, return_value_policy::copy);
|
||||
def("__init__", [](Type& value, Scalar i) { value = (Type)i; });
|
||||
def(init([](Scalar i) { return static_cast<Type>(i); }));
|
||||
def("__int__", [](Type value) { return (Scalar) value; });
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
def("__long__", [](Type value) { return (Scalar) value; });
|
||||
@ -1378,8 +1402,8 @@ public:
|
||||
}
|
||||
def("__hash__", [](const Type &value) { return (Scalar) value; });
|
||||
// Pickling and unpickling -- needed for use with the 'multiprocessing' module
|
||||
def("__getstate__", [](const Type &value) { return pybind11::make_tuple((Scalar) value); });
|
||||
def("__setstate__", [](Type &p, tuple t) { new (&p) Type((Type) t[0].cast<Scalar>()); });
|
||||
def(pickle([](const Type &value) { return pybind11::make_tuple((Scalar) value); },
|
||||
[](tuple t) { return static_cast<Type>(t[0].cast<Scalar>()); }));
|
||||
}
|
||||
|
||||
/// Export enumeration entries into the parent scope
|
||||
@ -1402,30 +1426,6 @@ private:
|
||||
handle m_parent;
|
||||
};
|
||||
|
||||
/// Binds an existing constructor taking arguments Args...
|
||||
template <typename... Args> detail::initimpl::constructor<Args...> init() { return {}; }
|
||||
/// Like `init<Args...>()`, but the instance is always constructed through the alias class (even
|
||||
/// when not inheriting on the Python side).
|
||||
template <typename... Args> detail::initimpl::alias_constructor<Args...> init_alias() { return {}; }
|
||||
|
||||
/// Binds a factory function as a constructor
|
||||
template <typename Func, typename Ret = detail::initimpl::factory<Func>>
|
||||
Ret init(Func &&f) { return {std::forward<Func>(f)}; }
|
||||
|
||||
/// Dual-argument factory function: the first function is called when no alias is needed, the second
|
||||
/// when an alias is needed (i.e. due to python-side inheritance). Arguments must be identical.
|
||||
template <typename CFunc, typename AFunc, typename Ret = detail::initimpl::factory<CFunc, AFunc>>
|
||||
Ret init(CFunc &&c, AFunc &&a) {
|
||||
return {std::forward<CFunc>(c), std::forward<AFunc>(a)};
|
||||
}
|
||||
|
||||
/// Binds pickling functions `__getstate__` and `__setstate__` and ensures that the type
|
||||
/// returned by `__getstate__` is the same as the argument accepted by `__setstate__`.
|
||||
template <typename GetState, typename SetState>
|
||||
detail::initimpl::pickle_factory<GetState, SetState> pickle(GetState &&g, SetState &&s) {
|
||||
return {std::forward<GetState>(g), std::forward<SetState>(s)};
|
||||
};
|
||||
|
||||
NAMESPACE_BEGIN(detail)
|
||||
|
||||
|
||||
|
@ -120,17 +120,13 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
||||
arg("x"),
|
||||
"Add an item to the end of the list");
|
||||
|
||||
cl.def("__init__", [](Vector &v, iterable it) {
|
||||
new (&v) Vector();
|
||||
try {
|
||||
v.reserve(len(it));
|
||||
cl.def(init([](iterable it) {
|
||||
auto v = std::unique_ptr<Vector>(new Vector());
|
||||
v->reserve(len(it));
|
||||
for (handle h : it)
|
||||
v.push_back(h.cast<T>());
|
||||
} catch (...) {
|
||||
v.~Vector();
|
||||
throw;
|
||||
}
|
||||
});
|
||||
v->push_back(h.cast<T>());
|
||||
return v.release();
|
||||
}));
|
||||
|
||||
cl.def("extend",
|
||||
[](Vector &v, const Vector &src) {
|
||||
@ -346,20 +342,22 @@ vector_buffer(Class_& cl) {
|
||||
return buffer_info(v.data(), static_cast<ssize_t>(sizeof(T)), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)});
|
||||
});
|
||||
|
||||
cl.def("__init__", [](Vector& vec, buffer buf) {
|
||||
cl.def(init([](buffer buf) {
|
||||
auto info = buf.request();
|
||||
if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T)))
|
||||
throw type_error("Only valid 1D buffers can be copied to a vector");
|
||||
if (!detail::compare_buffer_info<T>::compare(info) || (ssize_t) sizeof(T) != info.itemsize)
|
||||
throw type_error("Format mismatch (Python: " + info.format + " C++: " + format_descriptor<T>::format() + ")");
|
||||
new (&vec) Vector();
|
||||
vec.reserve((size_t) info.shape[0]);
|
||||
|
||||
auto vec = std::unique_ptr<Vector>(new Vector());
|
||||
vec->reserve((size_t) info.shape[0]);
|
||||
T *p = static_cast<T*>(info.ptr);
|
||||
ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
|
||||
T *end = p + info.shape[0] * step;
|
||||
for (; p != end; p += step)
|
||||
vec.push_back(*p);
|
||||
});
|
||||
vec->push_back(*p);
|
||||
return vec.release();
|
||||
}));
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -78,13 +78,15 @@ TEST_SUBMODULE(buffers, m) {
|
||||
py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
|
||||
.def(py::init<ssize_t, ssize_t>())
|
||||
/// Construct from a buffer
|
||||
.def("__init__", [](Matrix &v, py::buffer b) {
|
||||
.def(py::init([](py::buffer b) {
|
||||
py::buffer_info info = b.request();
|
||||
if (info.format != py::format_descriptor<float>::format() || info.ndim != 2)
|
||||
throw std::runtime_error("Incompatible buffer format!");
|
||||
new (&v) Matrix(info.shape[0], info.shape[1]);
|
||||
memcpy(v.data(), info.ptr, sizeof(float) * (size_t) (v.rows() * v.cols()));
|
||||
})
|
||||
|
||||
auto v = new Matrix(info.shape[0], info.shape[1]);
|
||||
memcpy(v->data(), info.ptr, sizeof(float) * (size_t) (v->rows() * v->cols()));
|
||||
return v;
|
||||
}))
|
||||
|
||||
.def("rows", &Matrix::rows)
|
||||
.def("cols", &Matrix::cols)
|
||||
|
Loading…
Reference in New Issue
Block a user