Merge pull request #12028 from s-hadinger/lvgl_cb

LVGL callbacks
This commit is contained in:
s-hadinger 2021-05-06 15:56:19 +02:00 committed by GitHub
commit 3c4acc9528
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 127 additions and 46 deletions

View File

@ -188,11 +188,119 @@ extern "C" {
// general form of lv_obj_t* function, up to 4 parameters
// We can only send 32 bits arguments (no 64 bits nor double) and we expect pointers to be 32 bits
#define LVBE_MAX_CALLBACK 6 // max 6 callbackss
#define LVBE_LVGL_CB "_lvgl_cb"
#define LVBE_LVGL_CB_OBJ "_lvgl_cb_obj" // remember which object it was linked to
#define LVBE_LVGL_CB_DISPATCH "_lvgl_cb_dispatch"
// General form of callback
typedef int32_t (*lvbe_callback)(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4);
int32_t lvbe_callback_x(uint32_t n, struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4);
// We define 6 callback vectors, this may need to be raised
int32_t lvbe_callback_0(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(0, obj, v1, v2, v3, v4);
}
int32_t lvbe_callback_1(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(1, obj, v1, v2, v3, v4);
}
int32_t lvbe_callback_2(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(2, obj, v1, v2, v3, v4);
}
int32_t lvbe_callback_3(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(3, obj, v1, v2, v3, v4);
}
int32_t lvbe_callback_4(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(4, obj, v1, v2, v3, v4);
}
int32_t lvbe_callback_5(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(5, obj, v1, v2, v3, v4);
}
const lvbe_callback lvbe_callbacks[LVBE_MAX_CALLBACK] = {
lvbe_callback_0,
lvbe_callback_1,
lvbe_callback_2,
lvbe_callback_3,
lvbe_callback_4,
lvbe_callback_5,
};
int32_t lvbe_callback_x(uint32_t n, struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
be_getglobal(berry.vm, LVBE_LVGL_CB_OBJ);
be_pushint(berry.vm, n);
be_pushint(berry.vm, (int32_t) obj);
be_pushint(berry.vm, v1);
be_pushint(berry.vm, v2);
be_pushint(berry.vm, v3);
be_pushint(berry.vm, v4);
be_pcall(berry.vm, 6);
int32_t ret = be_toint(berry.vm, -7);
be_pop(berry.vm, 7);
berry_log_P(">>>: Callback called%d", n);
return ret;
}
// read a single value at stack position idx, convert to int.
// if object instance, get `.p` member and convert it recursively
int32_t be_convert_single_elt(bvm *vm, int32_t idx, const char * arg_type = nullptr) {
int32_t be_convert_single_elt(bvm *vm, int32_t idx, const char * arg_type = nullptr, int32_t lv_obj_cb = 0) {
int32_t ret = 0;
char provided_type = 0;
idx = be_absindex(vm, idx); // make sure we have an absolute index
if (arg_type == nullptr) { arg_type = "."; } // if no type provided, replace with wildchar
size_t arg_type_len = strlen(arg_type);
// handle callbacks first, since a wrong parameter will always yield to a crash
if (arg_type_len == 1 && arg_type[0] >= '0' && arg_type[0] < '0' + LVBE_MAX_CALLBACK) {
if (be_isclosure(vm, idx)) {
// we're good
// berry_log_P(">> closure found idx %d", idx);
uint32_t cb_index = arg_type[0] - '0';
lvbe_callback func = lvbe_callbacks[cb_index];
// register the object
// record the closure
be_getglobal(vm, LVBE_LVGL_CB);
be_getmember(vm, -1, ".p");
be_pushint(vm, cb_index);
be_getindex(vm, -2);
// be_dumpstack(vm);
// stack: _lvgl_cb, list.p, index, map
be_moveto(vm, -1, -4);
be_pop(vm, 3);
// be_dumpstack(vm);
// stack: map
be_getmember(vm, -1, ".p");
be_pushint(vm, lv_obj_cb); // key - lv_obj
be_pushvalue(vm, idx); // value - closure
// stack map, map.p, key, value
be_setindex(vm, -3);
// be_dumpstack(vm);
// stack map, map.p, key, value
be_pop(vm, 4); // clean
// be_dumpstack(vm);
// record the object, it is always index #1
be_getglobal(vm, LVBE_LVGL_CB_OBJ);
be_getmember(vm, -1, ".p");
be_pushint(vm, cb_index);
be_getindex(vm, -2);
be_moveto(vm, -1, -4);
be_pop(vm, 3);
// stack: map
be_getmember(vm, -1, ".p");
be_pushint(vm, lv_obj_cb); // key - lv_obj as int
be_pushvalue(vm, 1); // value - lv_obj
// stack map, map.p, key, value
be_setindex(vm, -3);
be_pop(vm, 4); // clean
return (int32_t) func;
} else {
be_raise(vm, kTypeError, "Closure expected for callback type");
}
}
// first convert the value to int32
if (be_isint(vm, idx)) { ret = be_toint(vm, idx); provided_type = 'i'; }
@ -202,8 +310,6 @@ int32_t be_convert_single_elt(bvm *vm, int32_t idx, const char * arg_type = null
// check if simple type was a match
if (provided_type) {
if (arg_type == nullptr) { return ret; } // if no type check, return
size_t arg_type_len = strlen(arg_type);
if ((arg_type_len != 1) || ((arg_type[0] != provided_type) && arg_type[0] != '.') ) {
berry_log_P("Unexpected argument type '%c', expected '%s'", provided_type, arg_type);
}
@ -216,19 +322,21 @@ int32_t be_convert_single_elt(bvm *vm, int32_t idx, const char * arg_type = null
int32_t ret = be_convert_single_elt(vm, -1, nullptr); // recurse
be_pop(vm, 1);
if (arg_type != nullptr) {
if (arg_type_len > 1) {
// Check type
be_classof(vm, idx);
bool class_found = be_getglobal(vm, arg_type);
// Stack: class_of_idx, class_of_target (or nil)
if (class_found) {
if (!be_isderived(vm, -2)) {
berry_log_P("Unexpected class type '%s', expected '%s'", be_classname(vm, -2), arg_type);
berry_log_P("Unexpected class type '%s', expected '%s'", be_classname(vm, idx), arg_type);
}
} else {
berry_log_P("Unable to find class '%s'", arg_type);
berry_log_P("Unable to find class '%s' (%d)", arg_type, arg_type_len);
}
be_pop(vm, 2);
} else if (arg_type[0] != '.') {
berry_log_P("Unexpected instance type '%s', expected '%s'", be_classname(vm, idx), arg_type);
}
return ret;

View File

@ -142,45 +142,6 @@ extern void lv_ex_get_started_1(void);
* Calling any LVGL function with auto-mapping
*
\*********************************************************************************************/
// General form of callback
#define LVBE_MAX_CALLBACK 6 // max 6 callbackss
typedef int32_t (*lvbe_callback)(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4);
int32_t lvbe_callback_x(uint32_t n, struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4);
// We define 6 callback vectors, this may need to be raised
int32_t lvbe_callback_0(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(0, obj, v1, v2, v3, v4);
}
int32_t lvbe_callback_1(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(1, obj, v1, v2, v3, v4);
}
int32_t lvbe_callback_2(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(2, obj, v1, v2, v3, v4);
}
int32_t lvbe_callback_3(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(3, obj, v1, v2, v3, v4);
}
int32_t lvbe_callback_4(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(4, obj, v1, v2, v3, v4);
}
int32_t lvbe_callback_5(struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
return lvbe_callback_x(5, obj, v1, v2, v3, v4);
}
const lvbe_callback lvbe_callbacks[LVBE_MAX_CALLBACK] = {
lvbe_callback_0,
lvbe_callback_1,
lvbe_callback_2,
lvbe_callback_3,
lvbe_callback_4,
lvbe_callback_5,
};
int32_t lvbe_callback_x(uint32_t n, struct _lv_obj_t * obj, int32_t v1, int32_t v2, int32_t v3, int32_t v4) {
berry_log_P(">>>: Callback called%d", n);
return 0;
}
// check input parameters, and create callbacks if needed
// change values in place
@ -216,6 +177,7 @@ void be_check_arg_type(bvm *vm, int32_t argc, const char * arg_type, int32_t p[5
break;
case '&':
type_short_name[0] = arg_type[arg_idx+1];
type_short_name[1] = 0;
arg_idx += 2;
break;
case '(':
@ -239,7 +201,7 @@ void be_check_arg_type(bvm *vm, int32_t argc, const char * arg_type, int32_t p[5
}
}
// berry_log_P(">> be_call_c_func arg %i, type %s", i, arg_type_check ? type_short_name : "<null>");
p[i] = be_convert_single_elt(vm, i+1, arg_type_check ? type_short_name : nullptr);
p[i] = be_convert_single_elt(vm, i+1, arg_type_check ? type_short_name : nullptr, p[0]);
}
// check if we are missing arguments

View File

@ -374,6 +374,17 @@ const char berry_prog[] =
// "end "
// "lv = lvgl() "
"import lvgl as lv "
"_lvgl_cb = [ {}, {}, {}, {}, {}, {} ] "
"_lvgl_cb_obj = [ {}, {}, {}, {}, {}, {} ] "
"def _lvgl_cb_dispatch(idx, obj, v1, v2, v3, v4) "
"var func = _lvgl_cb[idx].find(obj) "
"var inst = _lvgl_cb_obj[idx].find(obj) "
"if func != nil "
"return func(inst, v1, v2, v3, v4) "
"end "
"return nil "
"end "
// array of 6 callback types, each with key (lv_obj pointer converted to int, closure)
#endif // USE_LVGL