1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
/*
* GridTools
*
* Copyright (c) 2014-2019, ETH Zurich
* All rights reserved.
*
* Please, refer to the LICENSE file in the root directory.
* SPDX-License-Identifier: BSD-3-Clause
*/
#pragma once
#include <type_traits>
#include <stdbool.h>
#include "common/any_moveable.hpp"
#include "fortran_array_view.hpp"
#include "handle_impl.hpp"
namespace cpp_bindgen {
namespace _impl {
template <class T, class = void>
struct result_converted_to_c;
template <class T>
struct result_converted_to_c<T,
typename std::enable_if<std::is_void<T>::value || std::is_arithmetic<T>::value>::type> {
using type = T;
};
template <class T>
struct result_converted_to_c<T,
typename std::enable_if<std::is_class<typename std::remove_reference<T>::type>::value>::type> {
using type = bindgen_handle *;
};
template <class T, class = void>
struct param_converted_to_c;
template <class T>
struct param_converted_to_c<T, typename std::enable_if<std::is_arithmetic<T>::value>::type> {
using type = T;
};
template <class T>
struct param_converted_to_c<T *, typename std::enable_if<std::is_arithmetic<T>::value>::type> {
using type = T *;
};
template <class T>
struct param_converted_to_c<T &, typename std::enable_if<std::is_arithmetic<T>::value>::type> {
using type = T *;
};
template <class T>
struct param_converted_to_c<T *,
typename std::enable_if<std::is_class<T>::value && !is_fortran_array_bindable<T *>::value>::type> {
using type = bindgen_handle *;
};
template <class T>
struct param_converted_to_c<T,
typename std::enable_if<std::is_class<remove_reference_t<T>>::value &&
!is_fortran_array_bindable<T>::value>::type> {
using type = bindgen_handle *;
};
template <class T>
struct param_converted_to_c<T, typename std::enable_if<is_fortran_array_bindable<T>::value>::type> {
using type = bindgen_fortran_array_descriptor *;
};
template <class T, typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0>
T convert_to_c(T obj) {
return obj;
}
template <class T,
typename std::enable_if<std::is_class<typename std::remove_reference<T>::type>::value, int>::type = 0>
bindgen_handle *convert_to_c(T &&obj) {
return new bindgen_handle{std::forward<T>(obj)};
}
template <class T>
using result_converted_to_c_t = typename result_converted_to_c<T>::type;
template <class T>
using param_converted_to_c_t = typename param_converted_to_c<T>::type;
template <class T,
typename std::enable_if<std::is_arithmetic<typename std::remove_pointer<T>::type>::value, int>::type = 0>
T convert_from_c(T obj) {
return obj;
};
template <class T,
typename std::enable_if<std::is_reference<T>::value &&
std::is_arithmetic<typename std::remove_reference<T>::type>::value,
int>::type = 0>
T convert_from_c(typename std::remove_reference<T>::type *obj) {
return *obj;
};
template <class T, typename std::enable_if<std::is_pointer<T>::value, int>::type = 0>
T convert_from_c(bindgen_handle *obj) {
return &any_cast<remove_pointer_t<T> &>(obj->m_value);
}
template <class T, typename std::enable_if<!std::is_pointer<T>::value, int>::type = 0>
T convert_from_c(bindgen_handle *obj) {
return any_cast<T>(obj->m_value);
}
template <class T>
T convert_from_c(bindgen_fortran_array_descriptor *obj) {
return make_fortran_array_view<T>(obj);
}
template <class T, class Impl>
struct wrapped_f;
template <class R, class... Params, class Impl>
struct wrapped_f<R(Params...), Impl> {
Impl m_fun;
result_converted_to_c_t<R> operator()(param_converted_to_c_t<Params>... args) const {
return convert_to_c(m_fun(convert_from_c<Params>(args)...));
}
};
template <class... Params, class Impl>
struct wrapped_f<void(Params...), Impl> {
Impl m_fun;
void operator()(param_converted_to_c_t<Params>... args) const { m_fun(convert_from_c<Params>(args)...); }
};
template <class T>
struct wrapped;
template <class T>
struct wrapped<T *> {
using type = typename wrapped<T>::type;
};
template <class T>
struct wrapped<T &> {
using type = typename wrapped<T>::type;
};
template <class R, class... Params>
struct wrapped<R(Params...)> {
using type = result_converted_to_c_t<R>(typename param_converted_to_c<Params>::type...);
};
} // namespace _impl
/// Transform a function type to to the function type that is callable from C
template <class T>
using wrapped_t = typename _impl::wrapped<T>::type;
/// Wrap the functor of type `Impl` to another functor that can be invoked with the 'wrapped_t<T>' signature.
template <class T, class Impl>
constexpr _impl::wrapped_f<T, typename std::decay<Impl>::type> wrap(Impl &&obj) {
return {std::forward<Impl>(obj)};
}
/// Specialization for function pointers.
template <class T>
constexpr _impl::wrapped_f<T, T *> wrap(T *obj) {
return {obj};
}
} // namespace cpp_bindgen
|