![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
A metronome using the FRDM K64F board
mbed-client/mbed-client/functionpointer.h@0:a7a43371b306, 2017-05-14 (annotated)
- Committer:
- ram54288
- Date:
- Sun May 14 18:40:18 2017 +0000
- Revision:
- 0:a7a43371b306
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ram54288 | 0:a7a43371b306 | 1 | /* |
ram54288 | 0:a7a43371b306 | 2 | * Copyright (c) 2015 ARM Limited. All rights reserved. |
ram54288 | 0:a7a43371b306 | 3 | * SPDX-License-Identifier: Apache-2.0 |
ram54288 | 0:a7a43371b306 | 4 | * Licensed under the Apache License, Version 2.0 (the License); you may |
ram54288 | 0:a7a43371b306 | 5 | * not use this file except in compliance with the License. |
ram54288 | 0:a7a43371b306 | 6 | * You may obtain a copy of the License at |
ram54288 | 0:a7a43371b306 | 7 | * |
ram54288 | 0:a7a43371b306 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
ram54288 | 0:a7a43371b306 | 9 | * |
ram54288 | 0:a7a43371b306 | 10 | * Unless required by applicable law or agreed to in writing, software |
ram54288 | 0:a7a43371b306 | 11 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT |
ram54288 | 0:a7a43371b306 | 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
ram54288 | 0:a7a43371b306 | 13 | * See the License for the specific language governing permissions and |
ram54288 | 0:a7a43371b306 | 14 | * limitations under the License. |
ram54288 | 0:a7a43371b306 | 15 | */ |
ram54288 | 0:a7a43371b306 | 16 | #ifndef FUNCTIONPOINTER_H |
ram54288 | 0:a7a43371b306 | 17 | #define FUNCTIONPOINTER_H |
ram54288 | 0:a7a43371b306 | 18 | |
ram54288 | 0:a7a43371b306 | 19 | #include <string.h> |
ram54288 | 0:a7a43371b306 | 20 | #include <stdint.h> |
ram54288 | 0:a7a43371b306 | 21 | |
ram54288 | 0:a7a43371b306 | 22 | /*! \file functionpointer.h |
ram54288 | 0:a7a43371b306 | 23 | * \brief A class for storing and calling a pointer to a static or member void function. |
ram54288 | 0:a7a43371b306 | 24 | */ |
ram54288 | 0:a7a43371b306 | 25 | |
ram54288 | 0:a7a43371b306 | 26 | template <typename R> |
ram54288 | 0:a7a43371b306 | 27 | class FP0{ |
ram54288 | 0:a7a43371b306 | 28 | public: |
ram54288 | 0:a7a43371b306 | 29 | /** Create a function pointer, attaching a static function. |
ram54288 | 0:a7a43371b306 | 30 | * |
ram54288 | 0:a7a43371b306 | 31 | * \param function The void static function to attach (default is none). |
ram54288 | 0:a7a43371b306 | 32 | */ |
ram54288 | 0:a7a43371b306 | 33 | FP0(R (*function)(void) = 0) { |
ram54288 | 0:a7a43371b306 | 34 | memset(_member,0,sizeof(_member)); |
ram54288 | 0:a7a43371b306 | 35 | attach(function); |
ram54288 | 0:a7a43371b306 | 36 | } |
ram54288 | 0:a7a43371b306 | 37 | |
ram54288 | 0:a7a43371b306 | 38 | /** Create a function pointer, attaching a member function. |
ram54288 | 0:a7a43371b306 | 39 | * |
ram54288 | 0:a7a43371b306 | 40 | * \param object The object pointer to invoke the member function on (the "this" pointer). |
ram54288 | 0:a7a43371b306 | 41 | * \param function The address of the void member function to attach. |
ram54288 | 0:a7a43371b306 | 42 | */ |
ram54288 | 0:a7a43371b306 | 43 | template<typename T> |
ram54288 | 0:a7a43371b306 | 44 | FP0(T *object, R (T::*member)(void)) { |
ram54288 | 0:a7a43371b306 | 45 | attach(object, member); |
ram54288 | 0:a7a43371b306 | 46 | } |
ram54288 | 0:a7a43371b306 | 47 | |
ram54288 | 0:a7a43371b306 | 48 | /** Attach a static function. |
ram54288 | 0:a7a43371b306 | 49 | * |
ram54288 | 0:a7a43371b306 | 50 | * \param function The void static function to attach (default is none). |
ram54288 | 0:a7a43371b306 | 51 | */ |
ram54288 | 0:a7a43371b306 | 52 | void attach(R (*function)(void)) { |
ram54288 | 0:a7a43371b306 | 53 | _p.function = function; |
ram54288 | 0:a7a43371b306 | 54 | _membercaller = 0; |
ram54288 | 0:a7a43371b306 | 55 | } |
ram54288 | 0:a7a43371b306 | 56 | |
ram54288 | 0:a7a43371b306 | 57 | /** Attach a member function. |
ram54288 | 0:a7a43371b306 | 58 | * |
ram54288 | 0:a7a43371b306 | 59 | * \param object The object pointer to invoke the member function on (the "this" pointer). |
ram54288 | 0:a7a43371b306 | 60 | * \param function The address of the void member function to attach. |
ram54288 | 0:a7a43371b306 | 61 | */ |
ram54288 | 0:a7a43371b306 | 62 | template<typename T> |
ram54288 | 0:a7a43371b306 | 63 | void attach(T *object, R (T::*member)(void)) { |
ram54288 | 0:a7a43371b306 | 64 | _p.object = static_cast<void*>(object); |
ram54288 | 0:a7a43371b306 | 65 | *reinterpret_cast<R (T::**)(void)>(_member) = member; |
ram54288 | 0:a7a43371b306 | 66 | _membercaller = &FP0::membercaller<T>; |
ram54288 | 0:a7a43371b306 | 67 | } |
ram54288 | 0:a7a43371b306 | 68 | |
ram54288 | 0:a7a43371b306 | 69 | /** Call the attached static or member function. |
ram54288 | 0:a7a43371b306 | 70 | */ |
ram54288 | 0:a7a43371b306 | 71 | R call(){ |
ram54288 | 0:a7a43371b306 | 72 | if (_membercaller == 0 && _p.function) { |
ram54288 | 0:a7a43371b306 | 73 | return _p.function(); |
ram54288 | 0:a7a43371b306 | 74 | } else if (_membercaller && _p.object) { |
ram54288 | 0:a7a43371b306 | 75 | return _membercaller(_p.object, _member); |
ram54288 | 0:a7a43371b306 | 76 | } |
ram54288 | 0:a7a43371b306 | 77 | return (R)0; |
ram54288 | 0:a7a43371b306 | 78 | } |
ram54288 | 0:a7a43371b306 | 79 | |
ram54288 | 0:a7a43371b306 | 80 | typedef R (*static_fp)(); |
ram54288 | 0:a7a43371b306 | 81 | static_fp get_function() const { |
ram54288 | 0:a7a43371b306 | 82 | return (R(*)())_p.function; |
ram54288 | 0:a7a43371b306 | 83 | } |
ram54288 | 0:a7a43371b306 | 84 | |
ram54288 | 0:a7a43371b306 | 85 | R operator ()(void) { |
ram54288 | 0:a7a43371b306 | 86 | return call(); |
ram54288 | 0:a7a43371b306 | 87 | } |
ram54288 | 0:a7a43371b306 | 88 | operator bool(void) { |
ram54288 | 0:a7a43371b306 | 89 | void *q = &_p.function; |
ram54288 | 0:a7a43371b306 | 90 | return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL); |
ram54288 | 0:a7a43371b306 | 91 | } |
ram54288 | 0:a7a43371b306 | 92 | |
ram54288 | 0:a7a43371b306 | 93 | private: |
ram54288 | 0:a7a43371b306 | 94 | template<typename T> |
ram54288 | 0:a7a43371b306 | 95 | static void membercaller(void *object, uintptr_t *member) { |
ram54288 | 0:a7a43371b306 | 96 | T* o = static_cast<T*>(object); |
ram54288 | 0:a7a43371b306 | 97 | R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member); |
ram54288 | 0:a7a43371b306 | 98 | (o->**m)(); |
ram54288 | 0:a7a43371b306 | 99 | } |
ram54288 | 0:a7a43371b306 | 100 | |
ram54288 | 0:a7a43371b306 | 101 | union { |
ram54288 | 0:a7a43371b306 | 102 | R (*function)(void); // static function pointer - 0 if none attached |
ram54288 | 0:a7a43371b306 | 103 | void *object; // object this pointer - 0 if none attached |
ram54288 | 0:a7a43371b306 | 104 | } _p; |
ram54288 | 0:a7a43371b306 | 105 | uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller |
ram54288 | 0:a7a43371b306 | 106 | R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object |
ram54288 | 0:a7a43371b306 | 107 | }; |
ram54288 | 0:a7a43371b306 | 108 | |
ram54288 | 0:a7a43371b306 | 109 | /* If we had variadic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */ |
ram54288 | 0:a7a43371b306 | 110 | |
ram54288 | 0:a7a43371b306 | 111 | /** A class for storing and calling a pointer to a static or member void function |
ram54288 | 0:a7a43371b306 | 112 | */ |
ram54288 | 0:a7a43371b306 | 113 | template <typename R, typename A1> |
ram54288 | 0:a7a43371b306 | 114 | class FP1{ |
ram54288 | 0:a7a43371b306 | 115 | public: |
ram54288 | 0:a7a43371b306 | 116 | /** Create a function pointer, attaching a static function. |
ram54288 | 0:a7a43371b306 | 117 | * |
ram54288 | 0:a7a43371b306 | 118 | * \param function The void static function to attach (default is none). |
ram54288 | 0:a7a43371b306 | 119 | */ |
ram54288 | 0:a7a43371b306 | 120 | FP1(R (*function)(A1) = 0) { |
ram54288 | 0:a7a43371b306 | 121 | memset(_member,0,sizeof(_member)); |
ram54288 | 0:a7a43371b306 | 122 | attach(function); |
ram54288 | 0:a7a43371b306 | 123 | } |
ram54288 | 0:a7a43371b306 | 124 | |
ram54288 | 0:a7a43371b306 | 125 | /** Create a function pointeer, attaching a member function. |
ram54288 | 0:a7a43371b306 | 126 | * |
ram54288 | 0:a7a43371b306 | 127 | * \param object The object pointer to invoke the member function on (the "this" pointer). |
ram54288 | 0:a7a43371b306 | 128 | * \param function The address of the void member function to attach. |
ram54288 | 0:a7a43371b306 | 129 | */ |
ram54288 | 0:a7a43371b306 | 130 | template<typename T> |
ram54288 | 0:a7a43371b306 | 131 | FP1(T *object, R (T::*member)(A1)) { |
ram54288 | 0:a7a43371b306 | 132 | attach(object, member); |
ram54288 | 0:a7a43371b306 | 133 | } |
ram54288 | 0:a7a43371b306 | 134 | |
ram54288 | 0:a7a43371b306 | 135 | /** Attach a static function. |
ram54288 | 0:a7a43371b306 | 136 | * |
ram54288 | 0:a7a43371b306 | 137 | * \param function The void static function to attach (default is none). |
ram54288 | 0:a7a43371b306 | 138 | */ |
ram54288 | 0:a7a43371b306 | 139 | void attach(R (*function)(A1)) { |
ram54288 | 0:a7a43371b306 | 140 | _p.function = function; |
ram54288 | 0:a7a43371b306 | 141 | _membercaller = 0; |
ram54288 | 0:a7a43371b306 | 142 | } |
ram54288 | 0:a7a43371b306 | 143 | |
ram54288 | 0:a7a43371b306 | 144 | /** Attach a member function. |
ram54288 | 0:a7a43371b306 | 145 | * |
ram54288 | 0:a7a43371b306 | 146 | * \param object The object pointer to invoke the member function on (the "this" pointer). |
ram54288 | 0:a7a43371b306 | 147 | * \param function The address of the void member function to attach. |
ram54288 | 0:a7a43371b306 | 148 | */ |
ram54288 | 0:a7a43371b306 | 149 | template<typename T> |
ram54288 | 0:a7a43371b306 | 150 | void attach(T *object, R (T::*member)(A1)) { |
ram54288 | 0:a7a43371b306 | 151 | _p.object = static_cast<void*>(object); |
ram54288 | 0:a7a43371b306 | 152 | *reinterpret_cast<R (T::**)(A1)>(_member) = member; |
ram54288 | 0:a7a43371b306 | 153 | _membercaller = &FP1::membercaller<T>; |
ram54288 | 0:a7a43371b306 | 154 | } |
ram54288 | 0:a7a43371b306 | 155 | |
ram54288 | 0:a7a43371b306 | 156 | /** Call the attached static or member function. |
ram54288 | 0:a7a43371b306 | 157 | */ |
ram54288 | 0:a7a43371b306 | 158 | R call(A1 a){ |
ram54288 | 0:a7a43371b306 | 159 | if (_membercaller == 0 && _p.function) { |
ram54288 | 0:a7a43371b306 | 160 | return _p.function(a); |
ram54288 | 0:a7a43371b306 | 161 | } else if (_membercaller && _p.object) { |
ram54288 | 0:a7a43371b306 | 162 | return _membercaller(_p.object, _member, a); |
ram54288 | 0:a7a43371b306 | 163 | } |
ram54288 | 0:a7a43371b306 | 164 | return (R)0; |
ram54288 | 0:a7a43371b306 | 165 | } |
ram54288 | 0:a7a43371b306 | 166 | |
ram54288 | 0:a7a43371b306 | 167 | typedef R (*static_fp)(); |
ram54288 | 0:a7a43371b306 | 168 | static_fp get_function() const { |
ram54288 | 0:a7a43371b306 | 169 | return (R(*)())_p.function; |
ram54288 | 0:a7a43371b306 | 170 | } |
ram54288 | 0:a7a43371b306 | 171 | |
ram54288 | 0:a7a43371b306 | 172 | R operator ()(A1 a) { |
ram54288 | 0:a7a43371b306 | 173 | return call(a); |
ram54288 | 0:a7a43371b306 | 174 | } |
ram54288 | 0:a7a43371b306 | 175 | operator bool(void) |
ram54288 | 0:a7a43371b306 | 176 | { |
ram54288 | 0:a7a43371b306 | 177 | void *q = &_p.function; |
ram54288 | 0:a7a43371b306 | 178 | return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL); |
ram54288 | 0:a7a43371b306 | 179 | } |
ram54288 | 0:a7a43371b306 | 180 | private: |
ram54288 | 0:a7a43371b306 | 181 | template<typename T> |
ram54288 | 0:a7a43371b306 | 182 | static void membercaller(void *object, uintptr_t *member, A1 a) { |
ram54288 | 0:a7a43371b306 | 183 | T* o = static_cast<T*>(object); |
ram54288 | 0:a7a43371b306 | 184 | R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member); |
ram54288 | 0:a7a43371b306 | 185 | (o->**m)(a); |
ram54288 | 0:a7a43371b306 | 186 | } |
ram54288 | 0:a7a43371b306 | 187 | |
ram54288 | 0:a7a43371b306 | 188 | union { |
ram54288 | 0:a7a43371b306 | 189 | R (*function)(A1); // static function pointer - 0 if none attached |
ram54288 | 0:a7a43371b306 | 190 | void *object; // object this pointer - 0 if none attached |
ram54288 | 0:a7a43371b306 | 191 | } _p; |
ram54288 | 0:a7a43371b306 | 192 | uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller |
ram54288 | 0:a7a43371b306 | 193 | R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object |
ram54288 | 0:a7a43371b306 | 194 | }; |
ram54288 | 0:a7a43371b306 | 195 | |
ram54288 | 0:a7a43371b306 | 196 | /** A class for storing and calling a pointer to a static or member void function. |
ram54288 | 0:a7a43371b306 | 197 | */ |
ram54288 | 0:a7a43371b306 | 198 | template <typename R, typename A1, typename A2> |
ram54288 | 0:a7a43371b306 | 199 | class FP2{ |
ram54288 | 0:a7a43371b306 | 200 | public: |
ram54288 | 0:a7a43371b306 | 201 | /** Create a function pointer, attaching a static function. |
ram54288 | 0:a7a43371b306 | 202 | * |
ram54288 | 0:a7a43371b306 | 203 | * \param function The void static function to attach (default is none). |
ram54288 | 0:a7a43371b306 | 204 | */ |
ram54288 | 0:a7a43371b306 | 205 | FP2(R (*function)(A1, A2) = 0) { |
ram54288 | 0:a7a43371b306 | 206 | memset(_member,0,sizeof(_member)); |
ram54288 | 0:a7a43371b306 | 207 | attach(function); |
ram54288 | 0:a7a43371b306 | 208 | } |
ram54288 | 0:a7a43371b306 | 209 | |
ram54288 | 0:a7a43371b306 | 210 | /** Create a function pointer, attaching a member function. |
ram54288 | 0:a7a43371b306 | 211 | * |
ram54288 | 0:a7a43371b306 | 212 | * \param object The object pointer to invoke the member function on (the "this" pointer). |
ram54288 | 0:a7a43371b306 | 213 | * \param function The address of the void member function to attach. |
ram54288 | 0:a7a43371b306 | 214 | */ |
ram54288 | 0:a7a43371b306 | 215 | template<typename T> |
ram54288 | 0:a7a43371b306 | 216 | FP2(T *object, R (T::*member)(A1, A2)) { |
ram54288 | 0:a7a43371b306 | 217 | attach(object, member); |
ram54288 | 0:a7a43371b306 | 218 | } |
ram54288 | 0:a7a43371b306 | 219 | |
ram54288 | 0:a7a43371b306 | 220 | /** Attach a static function. |
ram54288 | 0:a7a43371b306 | 221 | * |
ram54288 | 0:a7a43371b306 | 222 | * \param function The void static function to attach (default is none). |
ram54288 | 0:a7a43371b306 | 223 | */ |
ram54288 | 0:a7a43371b306 | 224 | void attach(R (*function)(A1, A2)) { |
ram54288 | 0:a7a43371b306 | 225 | _p.function = function; |
ram54288 | 0:a7a43371b306 | 226 | _membercaller = 0; |
ram54288 | 0:a7a43371b306 | 227 | } |
ram54288 | 0:a7a43371b306 | 228 | |
ram54288 | 0:a7a43371b306 | 229 | /** Attach a member function |
ram54288 | 0:a7a43371b306 | 230 | * |
ram54288 | 0:a7a43371b306 | 231 | * \param object The object pointer to invoke the member function on (the "this" pointer). |
ram54288 | 0:a7a43371b306 | 232 | * \param function The address of the void member function to attach. |
ram54288 | 0:a7a43371b306 | 233 | */ |
ram54288 | 0:a7a43371b306 | 234 | template<typename T> |
ram54288 | 0:a7a43371b306 | 235 | void attach(T *object, R (T::*member)(A1, A2)) { |
ram54288 | 0:a7a43371b306 | 236 | _p.object = static_cast<void*>(object); |
ram54288 | 0:a7a43371b306 | 237 | *reinterpret_cast<R (T::**)(A1, A2)>(_member) = member; |
ram54288 | 0:a7a43371b306 | 238 | _membercaller = &FP2::membercaller<T>; |
ram54288 | 0:a7a43371b306 | 239 | } |
ram54288 | 0:a7a43371b306 | 240 | |
ram54288 | 0:a7a43371b306 | 241 | /** Call the attached static or member function. |
ram54288 | 0:a7a43371b306 | 242 | */ |
ram54288 | 0:a7a43371b306 | 243 | R call(A1 a1, A2 a2){ |
ram54288 | 0:a7a43371b306 | 244 | if (_membercaller == 0 && _p.function) { |
ram54288 | 0:a7a43371b306 | 245 | return _p.function(a1, a2); |
ram54288 | 0:a7a43371b306 | 246 | } else if (_membercaller && _p.object) { |
ram54288 | 0:a7a43371b306 | 247 | return _membercaller(_p.object, _member, a1, a2); |
ram54288 | 0:a7a43371b306 | 248 | } |
ram54288 | 0:a7a43371b306 | 249 | return (R)0; |
ram54288 | 0:a7a43371b306 | 250 | } |
ram54288 | 0:a7a43371b306 | 251 | |
ram54288 | 0:a7a43371b306 | 252 | typedef R (*static_fp)(); |
ram54288 | 0:a7a43371b306 | 253 | static_fp get_function() const { |
ram54288 | 0:a7a43371b306 | 254 | return (R(*)())_p.function; |
ram54288 | 0:a7a43371b306 | 255 | } |
ram54288 | 0:a7a43371b306 | 256 | |
ram54288 | 0:a7a43371b306 | 257 | R operator ()(A1 a1, A2 a2) { |
ram54288 | 0:a7a43371b306 | 258 | return call(a1, a2); |
ram54288 | 0:a7a43371b306 | 259 | } |
ram54288 | 0:a7a43371b306 | 260 | operator bool(void) |
ram54288 | 0:a7a43371b306 | 261 | { |
ram54288 | 0:a7a43371b306 | 262 | void *q = &_p.function; |
ram54288 | 0:a7a43371b306 | 263 | return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL); |
ram54288 | 0:a7a43371b306 | 264 | } |
ram54288 | 0:a7a43371b306 | 265 | private: |
ram54288 | 0:a7a43371b306 | 266 | template<typename T> |
ram54288 | 0:a7a43371b306 | 267 | static void membercaller(void *object, uintptr_t *member, A1 a1, A2 a2) { |
ram54288 | 0:a7a43371b306 | 268 | T* o = static_cast<T*>(object); |
ram54288 | 0:a7a43371b306 | 269 | R (T::**m)(A1, A2) = reinterpret_cast<R (T::**)(A1, A2)>(member); |
ram54288 | 0:a7a43371b306 | 270 | (o->**m)(a1, a2); |
ram54288 | 0:a7a43371b306 | 271 | } |
ram54288 | 0:a7a43371b306 | 272 | |
ram54288 | 0:a7a43371b306 | 273 | union { |
ram54288 | 0:a7a43371b306 | 274 | R (*function)(A1, A2); // static function pointer - 0 if none attached |
ram54288 | 0:a7a43371b306 | 275 | void *object; // object this pointer - 0 if none attached |
ram54288 | 0:a7a43371b306 | 276 | } _p; |
ram54288 | 0:a7a43371b306 | 277 | uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller |
ram54288 | 0:a7a43371b306 | 278 | R (*_membercaller)(void*, uintptr_t*, A1, A2); // registered membercaller function to convert back and call _m.member on _object |
ram54288 | 0:a7a43371b306 | 279 | }; |
ram54288 | 0:a7a43371b306 | 280 | |
ram54288 | 0:a7a43371b306 | 281 | /** A class for storing and calling a pointer to a static or member void function. |
ram54288 | 0:a7a43371b306 | 282 | */ |
ram54288 | 0:a7a43371b306 | 283 | template <typename R, typename A1, typename A2, typename A3> |
ram54288 | 0:a7a43371b306 | 284 | class FP3{ |
ram54288 | 0:a7a43371b306 | 285 | public: |
ram54288 | 0:a7a43371b306 | 286 | /** Create a function pointer, attaching a static function. |
ram54288 | 0:a7a43371b306 | 287 | * |
ram54288 | 0:a7a43371b306 | 288 | * \param function The void static function to attach (default is none). |
ram54288 | 0:a7a43371b306 | 289 | */ |
ram54288 | 0:a7a43371b306 | 290 | FP3(R (*function)(A1, A2, A3) = 0) { |
ram54288 | 0:a7a43371b306 | 291 | memset(_member,0,sizeof(_member)); |
ram54288 | 0:a7a43371b306 | 292 | attach(function); |
ram54288 | 0:a7a43371b306 | 293 | } |
ram54288 | 0:a7a43371b306 | 294 | |
ram54288 | 0:a7a43371b306 | 295 | /** Create a function pointer, attaching a member function. |
ram54288 | 0:a7a43371b306 | 296 | * |
ram54288 | 0:a7a43371b306 | 297 | * \param object The object pointer to invoke the member function on (the "this" pointer). |
ram54288 | 0:a7a43371b306 | 298 | * \param function The address of the void member function to attach. |
ram54288 | 0:a7a43371b306 | 299 | */ |
ram54288 | 0:a7a43371b306 | 300 | template<typename T> |
ram54288 | 0:a7a43371b306 | 301 | FP3(T *object, R (T::*member)(A1, A2, A3)) { |
ram54288 | 0:a7a43371b306 | 302 | attach(object, member); |
ram54288 | 0:a7a43371b306 | 303 | } |
ram54288 | 0:a7a43371b306 | 304 | |
ram54288 | 0:a7a43371b306 | 305 | /** Attach a static function. |
ram54288 | 0:a7a43371b306 | 306 | * |
ram54288 | 0:a7a43371b306 | 307 | * \param function The void static function to attach (default is none). |
ram54288 | 0:a7a43371b306 | 308 | */ |
ram54288 | 0:a7a43371b306 | 309 | void attach(R (*function)(A1, A2, A3)) { |
ram54288 | 0:a7a43371b306 | 310 | _p.function = function; |
ram54288 | 0:a7a43371b306 | 311 | _membercaller = 0; |
ram54288 | 0:a7a43371b306 | 312 | } |
ram54288 | 0:a7a43371b306 | 313 | |
ram54288 | 0:a7a43371b306 | 314 | /** Attach a member function. |
ram54288 | 0:a7a43371b306 | 315 | * |
ram54288 | 0:a7a43371b306 | 316 | * \param object The object pointer to invoke the member function on (the "this" pointer). |
ram54288 | 0:a7a43371b306 | 317 | * \param function The address of the void member function to attach. |
ram54288 | 0:a7a43371b306 | 318 | */ |
ram54288 | 0:a7a43371b306 | 319 | template<typename T> |
ram54288 | 0:a7a43371b306 | 320 | void attach(T *object, R (T::*member)(A1, A2, A3)) { |
ram54288 | 0:a7a43371b306 | 321 | _p.object = static_cast<void*>(object); |
ram54288 | 0:a7a43371b306 | 322 | *reinterpret_cast<R (T::**)(A1, A2, A3)>(_member) = member; |
ram54288 | 0:a7a43371b306 | 323 | _membercaller = &FP3::membercaller<T>; |
ram54288 | 0:a7a43371b306 | 324 | } |
ram54288 | 0:a7a43371b306 | 325 | |
ram54288 | 0:a7a43371b306 | 326 | /** Call the attached static or member function. |
ram54288 | 0:a7a43371b306 | 327 | */ |
ram54288 | 0:a7a43371b306 | 328 | R call(A1 a1, A2 a2, A3 a3){ |
ram54288 | 0:a7a43371b306 | 329 | if (_membercaller == 0 && _p.function) { |
ram54288 | 0:a7a43371b306 | 330 | return _p.function(a1, a2, a3); |
ram54288 | 0:a7a43371b306 | 331 | } else if (_membercaller && _p.object) { |
ram54288 | 0:a7a43371b306 | 332 | return _membercaller(_p.object, _member, a1, a2, a3); |
ram54288 | 0:a7a43371b306 | 333 | } |
ram54288 | 0:a7a43371b306 | 334 | return (R)0; |
ram54288 | 0:a7a43371b306 | 335 | } |
ram54288 | 0:a7a43371b306 | 336 | |
ram54288 | 0:a7a43371b306 | 337 | typedef R (*static_fp)(); |
ram54288 | 0:a7a43371b306 | 338 | static_fp get_function() const { |
ram54288 | 0:a7a43371b306 | 339 | return (R(*)())_p.function; |
ram54288 | 0:a7a43371b306 | 340 | } |
ram54288 | 0:a7a43371b306 | 341 | |
ram54288 | 0:a7a43371b306 | 342 | R operator ()(A1 a1, A2 a2, A3 a3) { |
ram54288 | 0:a7a43371b306 | 343 | return call(a1, a2, a3); |
ram54288 | 0:a7a43371b306 | 344 | } |
ram54288 | 0:a7a43371b306 | 345 | operator bool(void) |
ram54288 | 0:a7a43371b306 | 346 | { |
ram54288 | 0:a7a43371b306 | 347 | void *q = &_p.function; |
ram54288 | 0:a7a43371b306 | 348 | return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL); |
ram54288 | 0:a7a43371b306 | 349 | } |
ram54288 | 0:a7a43371b306 | 350 | private: |
ram54288 | 0:a7a43371b306 | 351 | template<typename T> |
ram54288 | 0:a7a43371b306 | 352 | static void membercaller(void *object, uintptr_t *member, A1 a1, A2 a2, A3 a3) { |
ram54288 | 0:a7a43371b306 | 353 | T* o = static_cast<T*>(object); |
ram54288 | 0:a7a43371b306 | 354 | R (T::**m)(A1, A2, A3) = reinterpret_cast<R (T::**)(A1, A2, A3)>(member); |
ram54288 | 0:a7a43371b306 | 355 | (o->**m)(a1, a2, a3); |
ram54288 | 0:a7a43371b306 | 356 | } |
ram54288 | 0:a7a43371b306 | 357 | |
ram54288 | 0:a7a43371b306 | 358 | union { |
ram54288 | 0:a7a43371b306 | 359 | R (*function)(A1, A2, A3); // static function pointer - 0 if none attached |
ram54288 | 0:a7a43371b306 | 360 | void *object; // object this pointer - 0 if none attached |
ram54288 | 0:a7a43371b306 | 361 | } _p; |
ram54288 | 0:a7a43371b306 | 362 | uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller |
ram54288 | 0:a7a43371b306 | 363 | R (*_membercaller)(void*, uintptr_t*, A1, A2, A3); // registered membercaller function to convert back and call _m.member on _object |
ram54288 | 0:a7a43371b306 | 364 | }; |
ram54288 | 0:a7a43371b306 | 365 | |
ram54288 | 0:a7a43371b306 | 366 | typedef FP0<void> FP; |
ram54288 | 0:a7a43371b306 | 367 | |
ram54288 | 0:a7a43371b306 | 368 | #endif |