File: function_wrapper.hpp

package info (click to toggle)
gridtools 2.0.0-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 21,728 kB
  • sloc: cpp: 45,263; python: 9,383; javascript: 8,445; ansic: 2,564; sh: 509; f90: 370; makefile: 216
file content (168 lines) | stat: -rw-r--r-- 5,795 bytes parent folder | download | duplicates (3)
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