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
- Committer:
- Christopher Haster
- Date:
- 2016-04-17
- Revision:
- 13:4d8a50d4967e
- Parent:
- 12:a005f8ca5d36
- Child:
- 14:79be4e700cc9
File content as of revision 13:4d8a50d4967e:
/* Thunker * Thunk generating class for calling function objects through * context-less functions */ #ifndef THUNKER_H #define THUNKER_H #include "FuncPtr.h" namespace funcptr { extern "C" { #include "trampoline.h" } /** Thunk generating class for calling function objects */ class Thunker { public: /** Create a Thunker around a function */ Thunker(FuncPtr<void()> func = 0) { attach(func); _entry = reinterpret_cast<void(*)()>( trampoline_init(&_trampoline, &Thunker::thunk, this)); } /** Create a Thunker around a method */ template <typename T, typename M> Thunker(T *obj, M method) { attach(obj, method); _entry = reinterpret_cast<void(*)()>( trampoline_init(&_trampoline, &Thunker::thunk, this)); } /** Attach a function */ void attach(FuncPtr<void()> func) { _func.attach(func); } /** Attach a method */ template <typename T, typename M> void attach(T *obj, M method) { attach(FuncPtr<void()>(obj, method)); } /** Call the attached function */ void call() { return _func(); } /** Call the attached function */ void operator()() { return call(); } /** Test if function has be attached */ operator bool() const { return _func; } /** Static thunk for passing as C-style function * @param func Thunker to call passed as void pointer */ static void thunk(void *func) { return static_cast<Thunker*>(func)->call(); } /** Entry point into thunk into function */ entry_t *entry() { return _entry; } /** Entry point into thunk into function */ operator entry_t*() { return entry(); } private: entry_t *_entry; trampoline_t _trampoline; FuncPtr<void()> _func; }; } #endif