Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
FunctionPointer.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #ifndef MBED_FUNCTIONPOINTER_H 00017 #define MBED_FUNCTIONPOINTER_H 00018 00019 #include <string.h> 00020 #include <stdint.h> 00021 #include <stddef.h> 00022 #include <stdarg.h> 00023 #include <new> 00024 #include "FunctionPointerBase.h" 00025 #include "FunctionPointerBind.h" 00026 00027 namespace mbed { 00028 /** A class for storing and calling a pointer to a static or member void function without arguments 00029 */ 00030 template <typename R> 00031 class FunctionPointer0 : public FunctionPointerBase<R>{ 00032 public: 00033 typedef R(*static_fp)(void); 00034 typedef struct arg_struct{ 00035 } ArgStruct; 00036 /** Create a FunctionPointer, attaching a static function 00037 * 00038 * @param function The void static function to attach (default is none) 00039 */ 00040 FunctionPointer0(static_fp function = 0): 00041 FunctionPointerBase<R>() 00042 { 00043 attach(function); 00044 } 00045 00046 /** Create a FunctionPointer, attaching a member function 00047 * 00048 * @param object The object pointer to invoke the member function on (i.e. the this pointer) 00049 * @param function The address of the void member function to attach 00050 */ 00051 template<typename T> 00052 FunctionPointer0(T *object, R (T::*member)(void)): 00053 FunctionPointerBase<R>() 00054 { 00055 attach(object, member); 00056 } 00057 00058 /** Attach a static function 00059 * 00060 * @param function The void static function to attach (default is none) 00061 */ 00062 void attach(static_fp function) { 00063 FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function); 00064 FunctionPointerBase<R>::_membercaller = &FunctionPointer0::staticcaller; 00065 } 00066 00067 /** Attach a member function 00068 * 00069 * @param object The object pointer to invoke the member function on (i.e. the this pointer) 00070 * @param function The address of the void member function to attach 00071 */ 00072 template<typename T> 00073 void attach(T *object, R (T::*member)(void)) { 00074 FunctionPointerBase<R>::_object = static_cast<void*>(object); 00075 *reinterpret_cast<R (T::**)(void)>(FunctionPointerBase<R>::_member) = member; 00076 FunctionPointerBase<R>::_membercaller = &FunctionPointer0::membercaller<T>; 00077 } 00078 00079 /** Call the attached static or member function 00080 */ 00081 R call(){ 00082 return FunctionPointerBase<R>::call(NULL); 00083 } 00084 00085 FunctionPointerBind<R> bind() { 00086 FunctionPointerBind<R> fp; 00087 fp.bind(&FunctionPointerBase<R>::_nullops, (ArgStruct *) NULL, this); 00088 return fp; 00089 } 00090 00091 static_fp get_function()const { 00092 return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object); 00093 } 00094 00095 R operator ()(void) { 00096 return call(); 00097 } 00098 00099 private: 00100 template<typename T> 00101 static R membercaller(void *object, uintptr_t *member, void *arg) { 00102 (void) arg; 00103 T* o = static_cast<T*>(object); 00104 R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member); 00105 return (o->**m)(); 00106 } 00107 static R staticcaller(void *object, uintptr_t *member, void *arg) { 00108 (void) arg; 00109 (void) member; 00110 static_fp f = reinterpret_cast<static_fp>(object); 00111 return f(); 00112 } 00113 }; 00114 00115 /* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */ 00116 00117 /** A class for storing and calling a pointer to a static or member void function with one argument 00118 */ 00119 template <typename R, typename A1> 00120 class FunctionPointer1 : public FunctionPointerBase<R> { 00121 protected: 00122 typedef struct arg_struct{ 00123 A1 a1; 00124 arg_struct(const A1 *b1) { 00125 a1 = *b1; 00126 } 00127 } ArgStruct; 00128 00129 public: 00130 typedef R(*static_fp)(A1); 00131 /** Create a FunctionPointer, attaching a static function 00132 * 00133 * @param function The void static function to attach (default is none) 00134 */ 00135 FunctionPointer1(static_fp function = 0) { 00136 attach(function); 00137 } 00138 00139 /** Create a FunctionPointer, attaching a member function 00140 * 00141 * @param object The object pointer to invoke the member function on (i.e. the this pointer) 00142 * @param function The address of the void member function to attach 00143 */ 00144 template<typename T> 00145 FunctionPointer1(T *object, R (T::*member)(A1)) { 00146 attach(object, member); 00147 } 00148 00149 /** Attach a static function 00150 * 00151 * @param function The void static function to attach (default is none) 00152 */ 00153 void attach(static_fp function) { 00154 FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function); 00155 FunctionPointerBase<R>::_membercaller = &FunctionPointer1::staticcaller; 00156 } 00157 00158 /** Attach a member function 00159 * 00160 * @param object The object pointer to invoke the member function on (i.e. the this pointer) 00161 * @param function The address of the void member function to attach 00162 */ 00163 template<typename T> 00164 void attach(T *object, R (T::*member)(A1)) 00165 { 00166 FunctionPointerBase<R>::_object = static_cast<void*>(object); 00167 *reinterpret_cast<R (T::**)(A1)>(FunctionPointerBase<R>::_member) = member; 00168 FunctionPointerBase<R>::_membercaller = &FunctionPointer1::membercaller<T>; 00169 } 00170 00171 FunctionPointerBind<R> bind(const A1 &a1) { 00172 FunctionPointerBind<R> fp; 00173 fp.bind(&_fp1_ops, (ArgStruct *) NULL, this, &a1); 00174 return fp; 00175 } 00176 00177 00178 /** Call the attached static or member function 00179 */ 00180 R call(A1 a1) 00181 { 00182 ArgStruct Args(&a1); 00183 return FunctionPointerBase<R>::call(&Args); 00184 } 00185 00186 static_fp get_function()const 00187 { 00188 return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object); 00189 } 00190 00191 R operator ()(A1 a) { 00192 return call(a); 00193 } 00194 00195 private: 00196 template<typename T> 00197 static R membercaller(void *object, uintptr_t *member, void *arg) { 00198 ArgStruct *Args = static_cast<ArgStruct *>(arg); 00199 T* o = static_cast<T*>(object); 00200 R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member); 00201 return (o->**m)(Args->a1); 00202 } 00203 static R staticcaller(void *object, uintptr_t *member, void *arg) { 00204 ArgStruct *Args = static_cast<ArgStruct *>(arg); 00205 (void) member; 00206 static_fp f = reinterpret_cast<static_fp>(object); 00207 return f(Args->a1); 00208 } 00209 /* static void constructor(void * dest, va_list args) { 00210 new(dest) ArgStruct(va_arg(args,A1*)); 00211 } 00212 static void copy_constructor(void *dest , void* src) { 00213 ArgStruct *src_args = static_cast<ArgStruct *>(src); 00214 new(dest) ArgStruct(&(src_args->a1)); 00215 } 00216 static void destructor(void *args) { 00217 ArgStruct *argstruct = static_cast<ArgStruct *>(args); 00218 argstruct->~arg_struct(); 00219 } 00220 */ 00221 protected: 00222 static const struct FunctionPointerBase<R>::ArgOps _fp1_ops; 00223 }; 00224 00225 template <typename R, typename A1> 00226 const struct FunctionPointerBase<R>::ArgOps FunctionPointer1<R,A1>::_fp1_ops = { 00227 FunctionPointer1<R,A1>::constructor, 00228 FunctionPointer1<R,A1>::copy_constructor, 00229 FunctionPointer1<R,A1>::destructor 00230 }; 00231 00232 00233 /** A class for storing and calling a pointer to a static or member void function with two arguments 00234 */ 00235 template <typename R, typename A1, typename A2> 00236 class FunctionPointer2 : public FunctionPointerBase<R> { 00237 protected: 00238 typedef struct arg_struct{ 00239 A1 a1; 00240 A2 a2; 00241 arg_struct(const A1 *b1, const A2 *b2) { 00242 a1 = *b1; 00243 a2 = *b2; 00244 } 00245 } ArgStruct; 00246 00247 public: 00248 typedef R(*static_fp)(A1, A2); 00249 /** Create a FunctionPointer, attaching a static function 00250 * 00251 * @param function The void static function to attach (default is none) 00252 */ 00253 FunctionPointer2(static_fp function = 0) { 00254 attach(function); 00255 } 00256 00257 /** Create a FunctionPointer, attaching a member function 00258 * 00259 * @param object The object pointer to invoke the member function on (i.e. the this pointer) 00260 * @param function The address of the void member function to attach 00261 */ 00262 template<typename T> 00263 FunctionPointer2(T *object, R (T::*member)(A1, A2)) { 00264 attach(object, member); 00265 } 00266 00267 /** Attach a static function 00268 * 00269 * @param function The void static function to attach (default is none) 00270 */ 00271 void attach(static_fp function) { 00272 FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function); 00273 FunctionPointerBase<R>::_membercaller = &FunctionPointer2::staticcaller; 00274 } 00275 00276 /** Attach a member function 00277 * 00278 * @param object The object pointer to invoke the member function on (i.e. the this pointer) 00279 * @param function The address of the void member function to attach 00280 */ 00281 template<typename T> 00282 void attach(T *object, R (T::*member)(A1, A2)) 00283 { 00284 FunctionPointerBase<R>::_object = static_cast<void*>(object); 00285 *reinterpret_cast<R (T::**)(A1, A2)>(FunctionPointerBase<R>::_member) = member; 00286 FunctionPointerBase<R>::_membercaller = &FunctionPointer2::membercaller<T>; 00287 } 00288 00289 FunctionPointerBind<R> bind(const A1 &a1, const A2 &a2) { 00290 FunctionPointerBind<R> fp; 00291 fp.bind(&_fp2_ops, (ArgStruct *) NULL, this, &a1, &a2); 00292 return fp; 00293 } 00294 00295 00296 /** Call the attached static or member function 00297 */ 00298 R call(A1 a1, A2 a2) 00299 { 00300 ArgStruct Args(&a1, &a2); 00301 return FunctionPointerBase<R>::call(&Args); 00302 } 00303 00304 static_fp get_function()const 00305 { 00306 return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object); 00307 } 00308 00309 R operator ()(A1 a1, A2 a2) { 00310 return call(a1, a2); 00311 } 00312 00313 private: 00314 template<typename T> 00315 static R membercaller(void *object, uintptr_t *member, void *arg) { 00316 ArgStruct *Args = static_cast<ArgStruct *>(arg); 00317 T* o = static_cast<T*>(object); 00318 R (T::**m)(A1, A2) = reinterpret_cast<R (T::**)(A1, A2)>(member); 00319 return (o->**m)(Args->a1, Args->a2); 00320 } 00321 static R staticcaller(void *object, uintptr_t *member, void *arg) { 00322 ArgStruct *Args = static_cast<ArgStruct *>(arg); 00323 (void) member; 00324 static_fp f = reinterpret_cast<static_fp>(object); 00325 return f(Args->a1, Args->a2); 00326 } 00327 /* static void constructor(void * dest, va_list args) { 00328 A1 *a1 = va_arg(args, A1*); 00329 A2 *a2 = va_arg(args, A2*); 00330 new(dest) ArgStruct(a1, a2); 00331 } 00332 static void copy_constructor(void *dest , void* src) { 00333 ArgStruct *src_args = static_cast<ArgStruct *>(src); 00334 new(dest) ArgStruct(&(src_args->a1), &(src_args->a2)); 00335 } 00336 static void destructor(void *args) { 00337 ArgStruct *argstruct = static_cast<ArgStruct *>(args); 00338 argstruct->~arg_struct(); 00339 } 00340 */ 00341 protected: 00342 static const struct FunctionPointerBase<R>::ArgOps _fp2_ops; 00343 }; 00344 00345 template <typename R, typename A1, typename A2> 00346 const struct FunctionPointerBase<R>::ArgOps FunctionPointer2<R,A1,A2>::_fp2_ops = { 00347 FunctionPointer2<R,A1,A2>::constructor, 00348 FunctionPointer2<R,A1,A2>::copy_constructor, 00349 FunctionPointer2<R,A1,A2>::destructor 00350 }; 00351 00352 /** A class for storing and calling a pointer to a static or member void function with three arguments 00353 */ 00354 template <typename R, typename A1, typename A2, typename A3> 00355 class FunctionPointer3 : public FunctionPointerBase<R> { 00356 protected: 00357 typedef struct arg_struct{ 00358 A1 a1; 00359 A2 a2; 00360 A3 a3; 00361 arg_struct(const A1 *b1, const A2 *b2, const A3* b3) { 00362 a1 = *b1; 00363 a2 = *b2; 00364 a3 = *b3; 00365 } 00366 } ArgStruct; 00367 00368 public: 00369 typedef R(*static_fp)(A1, A2, A3); 00370 /** Create a FunctionPointer, attaching a static function 00371 * 00372 * @param function The void static function to attach (default is none) 00373 */ 00374 FunctionPointer3(static_fp function = 0) { 00375 attach(function); 00376 } 00377 00378 /** Create a FunctionPointer, attaching a member function 00379 * 00380 * @param object The object pointer to invoke the member function on (i.e. the this pointer) 00381 * @param function The address of the void member function to attach 00382 */ 00383 template<typename T> 00384 FunctionPointer3(T *object, R (T::*member)(A1, A2, A3)) { 00385 attach(object, member); 00386 } 00387 00388 /** Attach a static function 00389 * 00390 * @param function The void static function to attach (default is none) 00391 */ 00392 void attach(static_fp function) { 00393 FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function); 00394 FunctionPointerBase<R>::_membercaller = &FunctionPointer3::staticcaller; 00395 } 00396 00397 /** Attach a member function 00398 * 00399 * @param object The object pointer to invoke the member function on (i.e. the this pointer) 00400 * @param function The address of the void member function to attach 00401 */ 00402 template<typename T> 00403 void attach(T *object, R (T::*member)(A1, A2, A3)) 00404 { 00405 FunctionPointerBase<R>::_object = static_cast<void*>(object); 00406 *reinterpret_cast<R (T::**)(A1, A2, A3)>(FunctionPointerBase<R>::_member) = member; 00407 FunctionPointerBase<R>::_membercaller = &FunctionPointer3::membercaller<T>; 00408 } 00409 00410 FunctionPointerBind<R> bind(const A1 &a1, const A2 &a2, const A3 &a3) { 00411 FunctionPointerBind<R> fp; 00412 fp.bind(&_fp3_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3); 00413 return fp; 00414 } 00415 00416 00417 /** Call the attached static or member function 00418 */ 00419 R call(A1 a1, A2 a2, A3 a3) 00420 { 00421 ArgStruct Args(&a1, &a2, &a3); 00422 return FunctionPointerBase<R>::call(&Args); 00423 } 00424 00425 static_fp get_function()const 00426 { 00427 return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object); 00428 } 00429 00430 R operator ()(A1 a1, A2 a2, A3 a3) { 00431 return call(a1, a2, a3); 00432 } 00433 00434 private: 00435 template<typename T> 00436 static R membercaller(void *object, uintptr_t *member, void *arg) { 00437 ArgStruct *Args = static_cast<ArgStruct *>(arg); 00438 T* o = static_cast<T*>(object); 00439 R (T::**m)(A1, A2, A3) = reinterpret_cast<R (T::**)(A1, A2, A3)>(member); 00440 return (o->**m)(Args->a1, Args->a2, Args->a3); 00441 } 00442 static R staticcaller(void *object, uintptr_t *member, void *arg) { 00443 ArgStruct *Args = static_cast<ArgStruct *>(arg); 00444 (void) member; 00445 static_fp f = reinterpret_cast<static_fp>(object); 00446 return f(Args->a1, Args->a2, Args->a3); 00447 } 00448 /* static void constructor(void * dest, va_list args) { 00449 A1 *a1 = va_arg(args, A1*); 00450 A2 *a2 = va_arg(args, A2*); 00451 A3 *a3 = va_arg(args, A3*); 00452 new(dest) ArgStruct(a1, a2, a3); 00453 } 00454 static void copy_constructor(void *dest , void* src) { 00455 ArgStruct *src_args = static_cast<ArgStruct *>(src); 00456 new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3)); 00457 } 00458 static void destructor(void *args) { 00459 ArgStruct *argstruct = static_cast<ArgStruct *>(args); 00460 argstruct->~arg_struct(); 00461 } 00462 */ 00463 protected: 00464 static const struct FunctionPointerBase<R>::ArgOps _fp3_ops; 00465 }; 00466 00467 template <typename R, typename A1, typename A2, typename A3> 00468 const struct FunctionPointerBase<R>::ArgOps FunctionPointer3<R,A1,A2,A3>::_fp3_ops = { 00469 FunctionPointer3<R,A1,A2,A3>::constructor, 00470 FunctionPointer3<R,A1,A2,A3>::copy_constructor, 00471 FunctionPointer3<R,A1,A2,A3>::destructor 00472 }; 00473 00474 /** A class for storing and calling a pointer to a static or member void function with four arguments 00475 */ 00476 template <typename R, typename A1, typename A2, typename A3, typename A4> 00477 class FunctionPointer4 : public FunctionPointerBase<R> { 00478 protected: 00479 typedef struct arg_struct{ 00480 A1 a1; 00481 A2 a2; 00482 A3 a3; 00483 A4 a4; 00484 arg_struct(const A1 *b1, const A2 *b2, const A3* b3, const A4* b4) { 00485 a1 = *b1; 00486 a2 = *b2; 00487 a3 = *b3; 00488 a4 = *b4; 00489 } 00490 } ArgStruct; 00491 00492 public: 00493 typedef R(*static_fp)(A1, A2, A3, A4); 00494 /** Create a FunctionPointer, attaching a static function 00495 * 00496 * @param function The void static function to attach (default is none) 00497 */ 00498 FunctionPointer4(static_fp function = 0) { 00499 attach(function); 00500 } 00501 00502 /** Create a FunctionPointer, attaching a member function 00503 * 00504 * @param object The object pointer to invoke the member function on (i.e. the this pointer) 00505 * @param function The address of the void member function to attach 00506 */ 00507 template<typename T> 00508 FunctionPointer4(T *object, R (T::*member)(A1, A2, A3, A4)) { 00509 attach(object, member); 00510 } 00511 00512 /** Attach a static function 00513 * 00514 * @param function The void static function to attach (default is none) 00515 */ 00516 void attach(static_fp function) { 00517 FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function); 00518 FunctionPointerBase<R>::_membercaller = &FunctionPointer4::staticcaller; 00519 } 00520 00521 /** Attach a member function 00522 * 00523 * @param object The object pointer to invoke the member function on (i.e. the this pointer) 00524 * @param function The address of the void member function to attach 00525 */ 00526 template<typename T> 00527 void attach(T *object, R (T::*member)(A1, A2, A3, A4)) 00528 { 00529 FunctionPointerBase<R>::_object = static_cast<void*>(object); 00530 *reinterpret_cast<R (T::**)(A1, A2, A3, A4)>(FunctionPointerBase<R>::_member) = member; 00531 FunctionPointerBase<R>::_membercaller = &FunctionPointer4::membercaller<T>; 00532 } 00533 00534 FunctionPointerBind<R> bind(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) { 00535 FunctionPointerBind<R> fp; 00536 fp.bind(&_fp4_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3, &a4); 00537 return fp; 00538 } 00539 00540 00541 /** Call the attached static or member function 00542 */ 00543 R call(A1 a1, A2 a2, A3 a3, A4 a4) 00544 { 00545 ArgStruct Args(&a1, &a2, &a3, &a4); 00546 return FunctionPointerBase<R>::call(&Args); 00547 } 00548 00549 static_fp get_function()const 00550 { 00551 return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object); 00552 } 00553 00554 R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) { 00555 return call(a1, a2, a3, a4); 00556 } 00557 00558 private: 00559 template<typename T> 00560 static R membercaller(void *object, uintptr_t *member, void *arg) { 00561 ArgStruct *Args = static_cast<ArgStruct *>(arg); 00562 T* o = static_cast<T*>(object); 00563 R (T::**m)(A1, A2, A3, A4) = reinterpret_cast<R (T::**)(A1, A2, A3, A4)>(member); 00564 return (o->**m)(Args->a1, Args->a2, Args->a3, Args->a4); 00565 } 00566 static R staticcaller(void *object, uintptr_t *member, void *arg) { 00567 ArgStruct *Args = static_cast<ArgStruct *>(arg); 00568 (void) member; 00569 static_fp f = reinterpret_cast<static_fp>(object); 00570 return f(Args->a1, Args->a2, Args->a3, Args->a4); 00571 } 00572 /* static void constructor(void * dest, va_list args) { 00573 A1 *a1 = va_arg(args, A1*); 00574 A2 *a2 = va_arg(args, A2*); 00575 A3 *a3 = va_arg(args, A3*); 00576 A4 *a4 = va_arg(args, A4*); 00577 new(dest) ArgStruct(a1, a2, a3, a4); 00578 } 00579 static void copy_constructor(void *dest , void* src) { 00580 ArgStruct *src_args = static_cast<ArgStruct *>(src); 00581 new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3), &(src_args->a4)); 00582 } 00583 static void destructor(void *args) { 00584 ArgStruct *argstruct = static_cast<ArgStruct *>(args); 00585 argstruct->~arg_struct(); 00586 } 00587 */ 00588 protected: 00589 static const struct FunctionPointerBase<R>::ArgOps _fp4_ops; 00590 }; 00591 00592 template <typename R, typename A1, typename A2, typename A3, typename A4> 00593 const struct FunctionPointerBase<R>::ArgOps FunctionPointer4<R,A1,A2,A3,A4>::_fp4_ops = { 00594 FunctionPointer4<R,A1,A2,A3,A4>::constructor, 00595 FunctionPointer4<R,A1,A2,A3,A4>::copy_constructor, 00596 FunctionPointer4<R,A1,A2,A3,A4>::destructor 00597 }; 00598 00599 typedef FunctionPointer0<void> FunctionPointer; 00600 //typedef FunctionPointer1<void, int> event_callback_t; 00601 00602 } // namespace mbed 00603 00604 #endif
Generated on Tue Jul 12 2022 21:20:26 by
