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
|
/// Binds C++ enumerations and enumeration classes to Python
|
||||||
template <typename Type> class enum_ : public class_<Type> {
|
template <typename Type> class enum_ : public class_<Type> {
|
||||||
public:
|
public:
|
||||||
@ -1340,7 +1364,7 @@ public:
|
|||||||
m[kv.first] = kv.second;
|
m[kv.first] = kv.second;
|
||||||
return m;
|
return m;
|
||||||
}, return_value_policy::copy);
|
}, 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; });
|
def("__int__", [](Type value) { return (Scalar) value; });
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
def("__long__", [](Type value) { return (Scalar) value; });
|
def("__long__", [](Type value) { return (Scalar) value; });
|
||||||
@ -1378,8 +1402,8 @@ public:
|
|||||||
}
|
}
|
||||||
def("__hash__", [](const Type &value) { return (Scalar) value; });
|
def("__hash__", [](const Type &value) { return (Scalar) value; });
|
||||||
// Pickling and unpickling -- needed for use with the 'multiprocessing' module
|
// Pickling and unpickling -- needed for use with the 'multiprocessing' module
|
||||||
def("__getstate__", [](const Type &value) { return pybind11::make_tuple((Scalar) value); });
|
def(pickle([](const Type &value) { return pybind11::make_tuple((Scalar) value); },
|
||||||
def("__setstate__", [](Type &p, tuple t) { new (&p) Type((Type) t[0].cast<Scalar>()); });
|
[](tuple t) { return static_cast<Type>(t[0].cast<Scalar>()); }));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Export enumeration entries into the parent scope
|
/// Export enumeration entries into the parent scope
|
||||||
@ -1402,30 +1426,6 @@ private:
|
|||||||
handle m_parent;
|
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)
|
NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,17 +120,13 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
|||||||
arg("x"),
|
arg("x"),
|
||||||
"Add an item to the end of the list");
|
"Add an item to the end of the list");
|
||||||
|
|
||||||
cl.def("__init__", [](Vector &v, iterable it) {
|
cl.def(init([](iterable it) {
|
||||||
new (&v) Vector();
|
auto v = std::unique_ptr<Vector>(new Vector());
|
||||||
try {
|
v->reserve(len(it));
|
||||||
v.reserve(len(it));
|
for (handle h : it)
|
||||||
for (handle h : it)
|
v->push_back(h.cast<T>());
|
||||||
v.push_back(h.cast<T>());
|
return v.release();
|
||||||
} catch (...) {
|
}));
|
||||||
v.~Vector();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
cl.def("extend",
|
cl.def("extend",
|
||||||
[](Vector &v, const Vector &src) {
|
[](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)});
|
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();
|
auto info = buf.request();
|
||||||
if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T)))
|
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");
|
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)
|
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() + ")");
|
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);
|
T *p = static_cast<T*>(info.ptr);
|
||||||
ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
|
ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
|
||||||
T *end = p + info.shape[0] * step;
|
T *end = p + info.shape[0] * step;
|
||||||
for (; p != end; p += step)
|
for (; p != end; p += step)
|
||||||
vec.push_back(*p);
|
vec->push_back(*p);
|
||||||
});
|
return vec.release();
|
||||||
|
}));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -78,13 +78,15 @@ TEST_SUBMODULE(buffers, m) {
|
|||||||
py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
|
py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
|
||||||
.def(py::init<ssize_t, ssize_t>())
|
.def(py::init<ssize_t, ssize_t>())
|
||||||
/// Construct from a buffer
|
/// Construct from a buffer
|
||||||
.def("__init__", [](Matrix &v, py::buffer b) {
|
.def(py::init([](py::buffer b) {
|
||||||
py::buffer_info info = b.request();
|
py::buffer_info info = b.request();
|
||||||
if (info.format != py::format_descriptor<float>::format() || info.ndim != 2)
|
if (info.format != py::format_descriptor<float>::format() || info.ndim != 2)
|
||||||
throw std::runtime_error("Incompatible buffer format!");
|
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("rows", &Matrix::rows)
|
||||||
.def("cols", &Matrix::cols)
|
.def("cols", &Matrix::cols)
|
||||||
|
Loading…
Reference in New Issue
Block a user