| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -98,3 +98,53 @@ Then we can test the module: | |||
| 98 | 98 | we should compile and run the example from the same folder. | |
| 99 | 99 | To install, please consult | |
| 100 | 100 | `this pybind11 / CMake example <https://github.com/pybind/cmake_example>`_. | |
| 101 | + | ||
| 102 | + | ||
| 103 | + Fall-back cast | ||
| 104 | + ============== | ||
| 105 | + | ||
| 106 | + The previous example showed you how to design your module to be flexible in accepting data. | ||
| 107 | + From C++ we used ``xt::xarray<double>``, | ||
| 108 | + whereas for the Python API we used ``xt::pyarray<double>`` to operate directly on the memory | ||
| 109 | + of a NumPy array from Python (without copying the data). | ||
| 110 | + | ||
| 111 | + Sometimes, you might not have the flexibility to design your module's methods | ||
| 112 | + with template parameters. | ||
| 113 | + This might occur when you want to ``override`` functions | ||
| 114 | + (though it is recommended to use CRTP to still use templates). | ||
| 115 | + In this case we can still bind the module in Python using *xtensor-python*, | ||
| 116 | + however, we have to copy the data from a (NumPy) array. | ||
| 117 | + This means that although the following signatures are quite different when used from C++, | ||
| 118 | + as follows: | ||
| 119 | + | ||
| 120 | + 1. *Constant reference*: read from the data, without copying it. | ||
| 121 | + | ||
| 122 | + .. code-block:: cpp | ||
| 123 | + | ||
| 124 | + void foo(const xt::xarray<double>& a); | ||
| 125 | + | ||
| 126 | + 2. *Reference*: read from and/or write to the data, without copying it. | ||
| 127 | + | ||
| 128 | + .. code-block:: cpp | ||
| 129 | + | ||
| 130 | + void foo(xt::xarray<double>& a); | ||
| 131 | + | ||
| 132 | + 3. *Copy*: copy the data. | ||
| 133 | + | ||
| 134 | + .. code-block:: cpp | ||
| 135 | + | ||
| 136 | + void foo(xt::xarray<double> a); | ||
| 137 | + | ||
| 138 | + The Python will all cases result in a copy to a temporary variable | ||
| 139 | + (though the last signature will lead to a copy to a temporary variable, and another copy to ``a``). | ||
| 140 | + On the one hand, this is more costly than when using ``xt::pyarray`` and ``xt::pyxtensor``, | ||
| 141 | + on the other hand, it means that all changes you make to a reference, are made to the temporary | ||
| 142 | + copy, and are thus lost. | ||
| 143 | + | ||
| 144 | + Still, it might be a convenient way to create Python bindings, using a minimal effort. | ||
| 145 | + Consider this example: | ||
| 146 | + | ||
| 147 | + :download:`main.cpp <examples/copy_cast/main.cpp>` | ||
| 148 | + | ||
| 149 | + .. literalinclude:: examples/copy_cast/main.cpp | ||
| 150 | + :language: cpp | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,12 +4,14 @@ | |||
| 4 | 4 | #define FORCE_IMPORT_ARRAY | |
| 5 | 5 | #include <xtensor-python/pyarray.hpp> | |
| 6 | 6 | ||
| 7 | - double sum_of_sines(xt::pyarray<double>& m) | ||
| 7 | + template <class T> | ||
| 8 | + double sum_of_sines(T& m) | ||
| 8 | 9 | { | |
| 9 | 10 | auto sines = xt::sin(m); // sines does not actually hold values. | |
| 10 | 11 | return std::accumulate(sines.begin(), sines.end(), 0.0); | |
| 11 | 12 | } | |
| 12 | 13 | ||
| 14 | + // In the Python API this a reference to a temporary variable | ||
| 13 | 15 | double sum_of_cosines(const xt::xarray<double>& m) | |
| 14 | 16 | { | |
| 15 | 17 | auto cosines = xt::cos(m); // cosines does not actually hold values. | |
@@ -20,6 +22,6 @@ PYBIND11_MODULE(mymodule, m) | |||
| 20 | 22 | { | |
| 21 | 23 | xt::import_numpy(); | |
| 22 | 24 | m.doc() = "Test module for xtensor python bindings"; | |
| 23 | - m.def("sum_of_sines", sum_of_sines, "Sum the sines of the input values"); | ||
| 25 | + m.def("sum_of_sines", sum_of_sines<xt::pyarray<double>>, "Sum the sines of the input values"); | ||
| 24 | 26 | m.def("sum_of_cosines", sum_of_cosines, "Sum the cosines of the input values"); | |
| 25 | 27 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,8 +26,7 @@ namespace pybind11 | |||
| 26 | 26 | template <typename T, xt::layout_type L> | |
| 27 | 27 | struct xtensor_get_buffer | |
| 28 | 28 | { | |
| 29 | - template <typename H> | ||
| 30 | - static auto get(H src) | ||
| 29 | + static auto get(handle src) | ||
| 31 | 30 | { | |
| 32 | 31 | return array_t<T, array::c_style | array::forcecast>::ensure(src); | |
| 33 | 32 | } | |
@@ -36,8 +35,7 @@ namespace pybind11 | |||
| 36 | 35 | template <typename T> | |
| 37 | 36 | struct xtensor_get_buffer<T, xt::layout_type::column_major> | |
| 38 | 37 | { | |
| 39 | - template <typename H> | ||
| 40 | - static auto get(H src) | ||
| 38 | + static auto get(handle src) | ||
| 41 | 39 | { | |
| 42 | 40 | return array_t<T, array::f_style>::ensure(src); | |
| 43 | 41 | } | |
@@ -51,8 +49,7 @@ namespace pybind11 | |||
| 51 | 49 | template <class T, xt::layout_type L> | |
| 52 | 50 | struct xtensor_check_buffer<xt::xarray<T, L>> | |
| 53 | 51 | { | |
| 54 | - template <typename H> | ||
| 55 | - static auto get(H src) | ||
| 52 | + static auto get(handle src) | ||
| 56 | 53 | { | |
| 57 | 54 | auto buf = xtensor_get_buffer<T, L>::get(src); | |
| 58 | 55 | return buf; | |
@@ -62,8 +59,7 @@ namespace pybind11 | |||
| 62 | 59 | template <class T, std::size_t N, xt::layout_type L> | |
| 63 | 60 | struct xtensor_check_buffer<xt::xtensor<T, N, L>> | |
| 64 | 61 | { | |
| 65 | - template <typename H> | ||
| 66 | - static auto get(H src) | ||
| 62 | + static auto get(handle src) | ||
| 67 | 63 | { | |
| 68 | 64 | auto buf = xtensor_get_buffer<T, L>::get(src); | |
| 69 | 65 | if (buf.ndim() != N) { | |
@@ -76,8 +72,7 @@ namespace pybind11 | |||
| 76 | 72 | template <class CT, class S, xt::layout_type L, class FST> | |
| 77 | 73 | struct xtensor_check_buffer<xt::xstrided_view<CT, S, L, FST>> | |
| 78 | 74 | { | |
| 79 | - template <typename H> | ||
| 80 | - static auto get(H /*src*/) | ||
| 75 | + static auto get(handle /*src*/) | ||
| 81 | 76 | { | |
| 82 | 77 | return false; | |
| 83 | 78 | } | |
@@ -86,18 +81,17 @@ namespace pybind11 | |||
| 86 | 81 | template <class EC, xt::layout_type L, class SC, class Tag> | |
| 87 | 82 | struct xtensor_check_buffer<xt::xarray_adaptor<EC, L, SC, Tag>> | |
| 88 | 83 | { | |
| 89 | - template <typename H> | ||
| 90 | - static auto get(H /*src*/) | ||
| 84 | + static auto get(handle src) | ||
| 91 | 85 | { | |
| 92 | - return false; | ||
| 86 | + auto buf = xtensor_get_buffer<EC, L>::get(src); | ||
| 87 | + return buf; | ||
| 93 | 88 | } | |
| 94 | 89 | }; | |
| 95 | 90 | ||
| 96 | 91 | template <class EC, std::size_t N, xt::layout_type L, class Tag> | |
| 97 | 92 | struct xtensor_check_buffer<xt::xtensor_adaptor<EC, N, L, Tag>> | |
| 98 | 93 | { | |
| 99 | - template <typename H> | ||
| 100 | - static auto get(H /*src*/) | ||
| 94 | + static auto get(handle /*src*/) | ||
| 101 | 95 | { | |
| 102 | 96 | return false; | |
| 103 | 97 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments