| 427 | // Add the buffer interface to a vector |
| 428 | template <typename Vector, typename Class_, typename... Args> |
| 429 | void vector_buffer_impl(Class_ &cl, std::true_type) { |
| 430 | using T = typename Vector::value_type; |
| 431 | |
| 432 | static_assert(vector_has_data_and_format<Vector>::value, |
| 433 | "There is not an appropriate format descriptor for this vector"); |
| 434 | |
| 435 | // numpy.h declares this for arbitrary types, but it may raise an exception and crash hard |
| 436 | // at runtime if PYBIND11_NUMPY_DTYPE hasn't been called, so check here |
| 437 | format_descriptor<T>::format(); |
| 438 | |
| 439 | cl.def_buffer([](Vector &v) -> buffer_info { |
| 440 | return buffer_info(v.data(), |
| 441 | static_cast<ssize_t>(sizeof(T)), |
| 442 | format_descriptor<T>::format(), |
| 443 | 1, |
| 444 | {v.size()}, |
| 445 | {sizeof(T)}); |
| 446 | }); |
| 447 | |
| 448 | cl.def(init([](const buffer &buf) { |
| 449 | auto info = buf.request(); |
| 450 | if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T))) { |
| 451 | throw type_error("Only valid 1D buffers can be copied to a vector"); |
| 452 | } |
| 453 | if (!detail::compare_buffer_info<T>::compare(info) |
| 454 | || (ssize_t) sizeof(T) != info.itemsize) { |
| 455 | throw type_error("Format mismatch (Python: " + info.format |
| 456 | + " C++: " + format_descriptor<T>::format() + ")"); |
| 457 | } |
| 458 | |
| 459 | T *p = static_cast<T *>(info.ptr); |
| 460 | ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T)); |
| 461 | T *end = p + info.shape[0] * step; |
| 462 | if (step == 1) { |
| 463 | return Vector(p, end); |
| 464 | } |
| 465 | Vector vec; |
| 466 | vec.reserve((size_t) info.shape[0]); |
| 467 | for (; p != end; p += step) { |
| 468 | vec.push_back(*p); |
| 469 | } |
| 470 | return vec; |
| 471 | })); |
| 472 | |
| 473 | return; |
| 474 | } |
| 475 | |
| 476 | template <typename Vector, typename Class_, typename... Args> |
| 477 | void vector_buffer_impl(Class_ &, std::false_type) {} |