Flexible templated function class and related utilities that avoid dynamic memory allocation without limiting functionality
FuncPtr provides a flexible templated function class and related utilities while avoiding dynamic memory allocation and avoiding limited functionality.
FuncPtr provides an intuitive template interface:
FuncPtr<void(const char *)> func(puts); func("hello!\n"); // prints hello!
Several function types are supported by FuncPtr:
// Simple C functions void func(); FuncPtr<void()> fp(func); // C++ Methods struct Thing { void func(); }; Thing thing; FuncPtr<void()> fp(&thing, &Thing::func); // C functions with context void func(Thing *); FuncPtr<void()> fp(&thing, func); // Function objects struct Thing { void operator()(); }; Thing thing; FuncPtr<void()> fp(&thing);
There is no dynamic memory allocation, managing memory is placed entirely on the user. More advanced function manipulation can be accomplished with statically allocated classes:
// Function binding Binder<void(const char *), const char *> bind(putc, "hi!"); bind(); // prints hi! // Function composition Composer<int(const char *), const char *(int)> comp(puts, itoa); comp(10); // prints 10 // Function chaining Chainer<void(const char *), 2> chain; chain.attach(puts); chain.attach(puts); chain("hi!\n"); // prints hi! twice
FuncPtr allows easy support of a large range of function types in C++ APIs with very few lines of code:
class Thing { public: // The following two methods are sufficient for supporting // every supported function type void attach(FuncPtr<void()> func) { _func.attach(func); } template<typename T, typename M> void attach(T *obj, M method) { attach(FuncPtr<void()>(obj, method)); } private: FuncPtr<void()> _func; }
Additionally, FuncPtrs have several utilities for easy integration with C APIs:
// C style callbacks void register_callback(void (*callback)(void *), void *data); register_callback(&FuncPtr<void()>::thunk, &func); // C style functions without context void register_callback(void (*callback)()); Thunker thunk(func); register_callback(thunk); // mbed style callbacks void register_callback(T *obj, void (T::*M)()); register_callback(&func, &FuncPtr<void()>::call);
Thunker.h@13:4d8a50d4967e, 2016-04-17 (annotated)
- Committer:
- Christopher Haster
- Date:
- Sun Apr 17 21:15:30 2016 -0500
- Revision:
- 13:4d8a50d4967e
- Parent:
- 12:a005f8ca5d36
- Child:
- 14:79be4e700cc9
Added funcptr namespace
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Christopher Haster |
9:89aeb1297779 | 1 | /* Thunker |
Christopher Haster |
9:89aeb1297779 | 2 | * Thunk generating class for calling function objects through |
Christopher Haster |
9:89aeb1297779 | 3 | * context-less functions |
Christopher Haster |
9:89aeb1297779 | 4 | */ |
Christopher Haster |
9:89aeb1297779 | 5 | #ifndef THUNKER_H |
Christopher Haster |
9:89aeb1297779 | 6 | #define THUNKER_H |
Christopher Haster |
9:89aeb1297779 | 7 | |
Christopher Haster |
9:89aeb1297779 | 8 | #include "FuncPtr.h" |
Christopher Haster |
9:89aeb1297779 | 9 | |
Christopher Haster |
13:4d8a50d4967e | 10 | namespace funcptr { |
Christopher Haster |
13:4d8a50d4967e | 11 | |
Christopher Haster |
12:a005f8ca5d36 | 12 | extern "C" { |
Christopher Haster |
12:a005f8ca5d36 | 13 | #include "trampoline.h" |
Christopher Haster |
9:89aeb1297779 | 14 | } |
Christopher Haster |
9:89aeb1297779 | 15 | |
Christopher Haster |
9:89aeb1297779 | 16 | |
Christopher Haster |
10:086f34a27a8d | 17 | /** Thunk generating class for calling function objects |
Christopher Haster |
9:89aeb1297779 | 18 | */ |
Christopher Haster |
9:89aeb1297779 | 19 | class Thunker { |
Christopher Haster |
9:89aeb1297779 | 20 | public: |
Christopher Haster |
9:89aeb1297779 | 21 | /** Create a Thunker around a function |
Christopher Haster |
9:89aeb1297779 | 22 | */ |
Christopher Haster |
9:89aeb1297779 | 23 | Thunker(FuncPtr<void()> func = 0) { |
Christopher Haster |
9:89aeb1297779 | 24 | attach(func); |
Christopher Haster |
9:89aeb1297779 | 25 | _entry = reinterpret_cast<void(*)()>( |
Christopher Haster |
9:89aeb1297779 | 26 | trampoline_init(&_trampoline, &Thunker::thunk, this)); |
Christopher Haster |
9:89aeb1297779 | 27 | } |
Christopher Haster |
9:89aeb1297779 | 28 | |
Christopher Haster |
9:89aeb1297779 | 29 | /** Create a Thunker around a method |
Christopher Haster |
9:89aeb1297779 | 30 | */ |
Christopher Haster |
9:89aeb1297779 | 31 | template <typename T, typename M> |
Christopher Haster |
9:89aeb1297779 | 32 | Thunker(T *obj, M method) { |
Christopher Haster |
9:89aeb1297779 | 33 | attach(obj, method); |
Christopher Haster |
9:89aeb1297779 | 34 | _entry = reinterpret_cast<void(*)()>( |
Christopher Haster |
9:89aeb1297779 | 35 | trampoline_init(&_trampoline, &Thunker::thunk, this)); |
Christopher Haster |
9:89aeb1297779 | 36 | } |
Christopher Haster |
9:89aeb1297779 | 37 | |
Christopher Haster |
9:89aeb1297779 | 38 | /** Attach a function |
Christopher Haster |
9:89aeb1297779 | 39 | */ |
Christopher Haster |
9:89aeb1297779 | 40 | void attach(FuncPtr<void()> func) { |
Christopher Haster |
9:89aeb1297779 | 41 | _func.attach(func); |
Christopher Haster |
9:89aeb1297779 | 42 | } |
Christopher Haster |
9:89aeb1297779 | 43 | |
Christopher Haster |
9:89aeb1297779 | 44 | /** Attach a method |
Christopher Haster |
9:89aeb1297779 | 45 | */ |
Christopher Haster |
9:89aeb1297779 | 46 | template <typename T, typename M> |
Christopher Haster |
9:89aeb1297779 | 47 | void attach(T *obj, M method) { |
Christopher Haster |
9:89aeb1297779 | 48 | attach(FuncPtr<void()>(obj, method)); |
Christopher Haster |
9:89aeb1297779 | 49 | } |
Christopher Haster |
9:89aeb1297779 | 50 | |
Christopher Haster |
9:89aeb1297779 | 51 | /** Call the attached function |
Christopher Haster |
9:89aeb1297779 | 52 | */ |
Christopher Haster |
9:89aeb1297779 | 53 | void call() { |
Christopher Haster |
9:89aeb1297779 | 54 | return _func(); |
Christopher Haster |
9:89aeb1297779 | 55 | } |
Christopher Haster |
9:89aeb1297779 | 56 | |
Christopher Haster |
9:89aeb1297779 | 57 | /** Call the attached function |
Christopher Haster |
9:89aeb1297779 | 58 | */ |
Christopher Haster |
9:89aeb1297779 | 59 | void operator()() { |
Christopher Haster |
9:89aeb1297779 | 60 | return call(); |
Christopher Haster |
9:89aeb1297779 | 61 | } |
Christopher Haster |
9:89aeb1297779 | 62 | |
Christopher Haster |
9:89aeb1297779 | 63 | /** Test if function has be attached |
Christopher Haster |
9:89aeb1297779 | 64 | */ |
Christopher Haster |
9:89aeb1297779 | 65 | operator bool() const { |
Christopher Haster |
9:89aeb1297779 | 66 | return _func; |
Christopher Haster |
9:89aeb1297779 | 67 | } |
Christopher Haster |
9:89aeb1297779 | 68 | |
Christopher Haster |
9:89aeb1297779 | 69 | /** Static thunk for passing as C-style function |
Christopher Haster |
9:89aeb1297779 | 70 | * @param func Thunker to call passed as void pointer |
Christopher Haster |
9:89aeb1297779 | 71 | */ |
Christopher Haster |
9:89aeb1297779 | 72 | static void thunk(void *func) { |
Christopher Haster |
9:89aeb1297779 | 73 | return static_cast<Thunker*>(func)->call(); |
Christopher Haster |
9:89aeb1297779 | 74 | } |
Christopher Haster |
9:89aeb1297779 | 75 | |
Christopher Haster |
9:89aeb1297779 | 76 | /** Entry point into thunk into function |
Christopher Haster |
9:89aeb1297779 | 77 | */ |
Christopher Haster |
12:a005f8ca5d36 | 78 | entry_t *entry() { |
Christopher Haster |
9:89aeb1297779 | 79 | return _entry; |
Christopher Haster |
9:89aeb1297779 | 80 | } |
Christopher Haster |
9:89aeb1297779 | 81 | |
Christopher Haster |
9:89aeb1297779 | 82 | /** Entry point into thunk into function |
Christopher Haster |
9:89aeb1297779 | 83 | */ |
Christopher Haster |
12:a005f8ca5d36 | 84 | operator entry_t*() { |
Christopher Haster |
9:89aeb1297779 | 85 | return entry(); |
Christopher Haster |
9:89aeb1297779 | 86 | } |
Christopher Haster |
9:89aeb1297779 | 87 | |
Christopher Haster |
9:89aeb1297779 | 88 | private: |
Christopher Haster |
12:a005f8ca5d36 | 89 | entry_t *_entry; |
Christopher Haster |
9:89aeb1297779 | 90 | trampoline_t _trampoline; |
Christopher Haster |
9:89aeb1297779 | 91 | FuncPtr<void()> _func; |
Christopher Haster |
9:89aeb1297779 | 92 | }; |
Christopher Haster |
9:89aeb1297779 | 93 | |
Christopher Haster |
9:89aeb1297779 | 94 | |
Christopher Haster |
13:4d8a50d4967e | 95 | } |
Christopher Haster |
13:4d8a50d4967e | 96 | |
Christopher Haster |
9:89aeb1297779 | 97 | #endif |