@@ -68,6 +68,87 @@ MP_DEFINE_CONST_OBJ_TYPE(
68
68
locals_dict , & example_Timer_locals_dict
69
69
);
70
70
71
+ // What follows is a *separate* class definition that demonstrates more
72
+ // advanced techniques to implement other Python-like features, such as:
73
+ //
74
+ // - A custom representation for __repr__ and __str__.
75
+ // - Custom attribute handling to create a read/write "property".
76
+ //
77
+ // It re-uses some of the elements of the basic Timer class. This is allowed
78
+ // because they both use example_Timer_obj_t as the instance structure.
79
+
80
+ // Handles AdvancedTimer.__repr__, AdvancedTimer.__str__.
81
+ static void example_AdvancedTimer_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
82
+
83
+ // Get the elapsed time. In this case, it's also a demonstration of calling
84
+ // the equivalent of self.time() in the C API. This is not usually very
85
+ // efficient, but it can sometimes be useful.
86
+ mp_uint_t elapsed = mp_obj_get_int (example_Timer_time (self_in ));
87
+
88
+ // We'll make all representations print at least the class name.
89
+ mp_printf (print , "%q()" , MP_QSTR_AdvancedTimer );
90
+
91
+ // Decide what else to print based on print kind.
92
+ if (kind == PRINT_STR ) {
93
+ // For __str__, let's attempt to make it more readable.
94
+ mp_printf (print , " # created %d seconds ago" , elapsed / 1000 );
95
+ }
96
+ }
97
+
98
+ // Handles AdvancedTimer.seconds for reading and writing.
99
+ static void example_AdvancedTimer_attribute_handler (mp_obj_t self_in , qstr attr , mp_obj_t * dest ) {
100
+
101
+ // In this example, we only want to handle the .seconds attribute in a
102
+ // special way.
103
+ if (attr != MP_QSTR_seconds ) {
104
+ // Attribute not found, continue lookup in locals dict. This way,
105
+ // methods like .time() will be handled normally.
106
+ dest [1 ] = MP_OBJ_SENTINEL ;
107
+ return ;
108
+ }
109
+
110
+ // Get reference to AdvancedTimer instance.
111
+ example_Timer_obj_t * self = MP_OBJ_TO_PTR (self_in );
112
+
113
+ // Check if this is a read operation.
114
+ if (dest [0 ] == MP_OBJ_NULL ) {
115
+ // It's read, so "return" elapsed seconds by storing it in dest[0].
116
+ mp_uint_t elapsed = mp_hal_ticks_ms () - self -> start_time ;
117
+ dest [0 ] = mp_obj_new_int_from_uint (elapsed / 1000 );
118
+ return ;
119
+ }
120
+ // Check if this is a delete or store operation.
121
+ else if (dest [0 ] == MP_OBJ_SENTINEL ) {
122
+ // It's delete or store. Now check which one.
123
+ if (dest [1 ] == MP_OBJ_NULL ) {
124
+ // It's delete. But in this example we don't want to allow it
125
+ // so we just return.
126
+ return ;
127
+ } else {
128
+ // It's write. First, get the value that the user is trying to set.
129
+ mp_uint_t desired_ms = mp_obj_get_int (dest [1 ]) * 1000 ;
130
+ // Use it to update the start time. This way, the next read will
131
+ // report the updated time.
132
+ self -> start_time = mp_hal_ticks_ms () - desired_ms ;
133
+
134
+ // Indicate successful store.
135
+ dest [0 ] = MP_OBJ_NULL ;
136
+ return ;
137
+ }
138
+ }
139
+ }
140
+
141
+ // This defines the type(AdvancedTimer) object.
142
+ MP_DEFINE_CONST_OBJ_TYPE (
143
+ example_type_AdvancedTimer ,
144
+ MP_QSTR_AdvancedTimer ,
145
+ MP_TYPE_FLAG_NONE ,
146
+ attr , example_AdvancedTimer_attribute_handler ,
147
+ print , example_AdvancedTimer_print ,
148
+ make_new , example_Timer_make_new ,
149
+ locals_dict , & example_Timer_locals_dict
150
+ );
151
+
71
152
// Define all attributes of the module.
72
153
// Table entries are key/value pairs of the attribute name (a string)
73
154
// and the MicroPython object reference.
@@ -77,6 +158,7 @@ static const mp_rom_map_elem_t example_module_globals_table[] = {
77
158
{ MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_cexample ) },
78
159
{ MP_ROM_QSTR (MP_QSTR_add_ints ), MP_ROM_PTR (& example_add_ints_obj ) },
79
160
{ MP_ROM_QSTR (MP_QSTR_Timer ), MP_ROM_PTR (& example_type_Timer ) },
161
+ { MP_ROM_QSTR (MP_QSTR_AdvancedTimer ), MP_ROM_PTR (& example_type_AdvancedTimer ) },
80
162
};
81
163
static MP_DEFINE_CONST_DICT (example_module_globals , example_module_globals_table ) ;
82
164
0 commit comments