Commit | Line | Data |
---|---|---|
8b8b3339 AW |
1 | /* |
2 | Copyright (c) 2011 Andy Kirkham | |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
4 | of this software and associated documentation files (the "Software"), to deal | |
5 | in the Software without restriction, including without limitation the rights | |
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
7 | copies of the Software, and to permit persons to whom the Software is | |
8 | furnished to do so, subject to the following conditions: | |
9 | The above copyright notice and this permission notice shall be included in | |
10 | all copies or substantial portions of the Software. | |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
17 | THE SOFTWARE. | |
18 | */ | |
19 | ||
20 | #ifndef AJK_FPOINTER_H | |
21 | #define AJK_FPOINTER_H | |
5673fe39 | 22 | |
8b8b3339 AW |
23 | #ifndef NULL |
24 | #define NULL 0 | |
25 | #endif | |
5673fe39 MM |
26 | |
27 | #include <cstdint> | |
28 | ||
8b8b3339 AW |
29 | namespace AjK { |
30 | ||
31 | class FPointerDummy; | |
32 | ||
33 | /** FPointer - Adds callbacks that take and return a 32bit uint32_t data type. | |
34 | * | |
35 | * The Mbed library supplies a callback using the FunctionPointer object as | |
36 | * defined in FunctionPointer.h However, this callback system does not allow | |
37 | * the caller to pass a value to the callback. Likewise, the callback itself | |
38 | * cannot return a value. | |
39 | * | |
40 | * FPointer operates in the same way but allows the callback function to be | |
41 | * passed one arg, a uint32_t value. Additionally, the callback can return | |
42 | * a single uint32_t value. The reason for using uint32_t is that the Mbed | |
43 | * and the microcontroller (LPC1768) have a natural data size of 32bits and | |
44 | * this means we can use the uint32_t as a pointer. See example1.h for more | |
45 | * information. This example passes an "int" by passing a pointer to that | |
46 | * int as a 32bit value. Using this technique you can pass any value you like. | |
47 | * All you have to do is pass a pointer to your value cast to (uint32_t). Your | |
48 | * callback can the deference it to get the original value. | |
49 | * | |
50 | * example2.h shows how to do the same thing but demostrates how to specify | |
51 | * the callback into a class object/method. | |
52 | * | |
53 | * Finally, example3.h shows how to pass multiple values. In this example we | |
54 | * define a data structure and in the callback we pass a pointer to that | |
55 | * data structure thus allowing the callback to again get the values. | |
56 | * | |
57 | * Note, when passing pointers to variables to the callback, if the callback | |
58 | * function/method changes that variable's value then it will also change the | |
59 | * value the caller sees. If C pointers are new to you, you are strongly | |
60 | * advised to read up on the subject. It's pointers that often get beginners | |
61 | * into trouble when mis-used. | |
62 | * | |
63 | * @see example1.h | |
64 | * @see example2.h | |
65 | * @see example3.h | |
66 | * @see http://mbed.org/handbook/C-Data-Types | |
67 | * @see http://mbed.org/projects/libraries/svn/mbed/trunk/FunctionPointer.h | |
68 | */ | |
69 | class FPointer { | |
70 | ||
71 | protected: | |
72 | ||
73 | //! C callback function pointer. | |
74 | uint32_t (*c_callback)(uint32_t); | |
75 | ||
76 | //! C++ callback object/method pointer (the object part). | |
77 | FPointerDummy *obj_callback; | |
78 | ||
79 | //! C++ callback object/method pointer (the method part). | |
80 | uint32_t (FPointerDummy::*method_callback)(uint32_t); | |
81 | ||
82 | public: | |
83 | ||
84 | /** Constructor | |
85 | */ | |
86 | FPointer() { | |
87 | c_callback = NULL; | |
88 | obj_callback = NULL; | |
89 | method_callback = NULL; | |
90 | } | |
91 | ||
92 | /** attach - Overloaded attachment function. | |
93 | * | |
94 | * Attach a C type function pointer as the callback. | |
95 | * | |
96 | * Note, the callback function prototype must be:- | |
97 | * @code | |
98 | * uint32_t myCallbackFunction(uint32_t); | |
99 | * @endcode | |
100 | * @param A C function pointer to call. | |
101 | */ | |
102 | void attach(uint32_t (*function)(uint32_t) = 0) { c_callback = function; } | |
103 | ||
104 | /** attach - Overloaded attachment function. | |
105 | * | |
106 | * Attach a C++ type object/method pointer as the callback. | |
107 | * | |
108 | * Note, the callback method prototype must be:- | |
109 | * @code | |
110 | * public: | |
111 | * uint32_t myCallbackFunction(uint32_t); | |
112 | * @endcode | |
113 | * @param A C++ object pointer. | |
114 | * @param A C++ method within the object to call. | |
115 | */ | |
116 | template<class T> | |
117 | void attach(T* item, uint32_t (T::*method)(uint32_t)) { | |
118 | obj_callback = (FPointerDummy *)item; | |
119 | method_callback = (uint32_t (FPointerDummy::*)(uint32_t))method; | |
120 | } | |
121 | ||
122 | /** call - Overloaded callback initiator. | |
123 | * | |
124 | * call the callback function. | |
125 | * | |
126 | * @param uint32_t The value to pass to the callback. | |
127 | * @return uint32_t The value the callback returns. | |
128 | */ | |
129 | uint32_t call(uint32_t arg) { | |
130 | if (c_callback != NULL) { | |
131 | return (*c_callback)(arg); | |
132 | } | |
133 | else { | |
134 | if (obj_callback != NULL && method_callback != NULL) { | |
135 | return (obj_callback->*method_callback)(arg); | |
136 | } | |
137 | } | |
138 | return (uint32_t)NULL; | |
139 | } | |
140 | ||
141 | /** call - Overloaded callback initiator. | |
142 | * | |
143 | * Call the callback function without passing an argument. | |
144 | * The callback itself is passed NULL. Note, the callback | |
145 | * prototype should still be <b>uint32_t callback(uint32_t)</b>. | |
146 | * | |
147 | * @return uint32_t The value the callback returns. | |
148 | */ | |
149 | uint32_t call(void) { | |
150 | if (c_callback != NULL) { | |
151 | return (*c_callback)((uint32_t)NULL); | |
152 | } | |
153 | else { | |
154 | if (obj_callback != NULL && method_callback != NULL) { | |
155 | return (obj_callback->*method_callback)((uint32_t)NULL); | |
156 | } | |
157 | } | |
158 | return (uint32_t)NULL; | |
159 | } | |
160 | }; | |
161 | ||
162 | }; // namespace AjK ends | |
163 | ||
164 | using namespace AjK; | |
165 | ||
166 | #endif |