improve lua binding.

This commit is contained in:
jim 2018-03-10 08:06:02 +08:00
parent 37decfbf27
commit 998ce389b1
16 changed files with 192 additions and 24 deletions

View File

@ -3,7 +3,7 @@ import sys
env=DefaultEnvironment().Clone()
env['LIBS'] = ['resource', 'fontbitmap', 'imageloaderbitmap', 'lua'] + env['LIBS']
env['LIBS'] = ['resource', 'fontbitmap', 'ui_loader', 'imageloaderbitmap', 'lua'] + env['LIBS']
env.Program('run_lua', ["run_lua.c", 'lftk_lua.c'])

1
lua/TODO.md Normal file
View File

@ -0,0 +1 @@
* 对this的类型检查。

View File

@ -1,3 +1,6 @@
#include "base/enums.h"
#include "ui_loader/ui_builder_default.h"
typedef struct _userdata_info_t {
const char* info;
void* data;
@ -7,6 +10,7 @@ static lua_State* s_current_L = NULL;
extern void luaL_openlib(lua_State* L, const char* libname, const luaL_Reg* l, int nup);
static int lftk_newuserdata(lua_State* L, void* data, const char* info, const char* metatable) {
char str[48];
userdata_info_t* udata = NULL;
return_value_if_fail(data != NULL, 0);
@ -16,6 +20,15 @@ static int lftk_newuserdata(lua_State* L, void* data, const char* info, const ch
udata->data = data;
udata->info = info;
if (strstr(info, "/widget_t") != NULL && strcmp(metatable, "lftk.widget_t") == 0) {
widget_t* widget = (widget_t*)data;
const key_type_value_t* kv = widget_name_find_by_value(widget->type);
if (kv != NULL) {
snprintf(str, sizeof(str), "lftk.%s_t", kv->name);
metatable = str;
}
}
if (metatable != NULL) {
luaL_getmetatable(L, metatable);
lua_setmetatable(L, -2);
@ -40,7 +53,7 @@ static const luaL_Reg* find_member(const luaL_Reg* funcs, const char* name) {
static void* lftk_checkudata(lua_State* L, int idx, const char* name) {
userdata_info_t* udata = (userdata_info_t*)lua_touserdata(L, idx);
if (udata) {
assert(strstr(udata->info, name) != NULL);
// assert(strstr(udata->info, name) != NULL);
return udata->data;
} else {
return NULL;

41
lua/demo2.lua Normal file
View File

@ -0,0 +1,41 @@
function on_click(ctx, evt)
print('on_click');
end
function application_init()
local win = Window.open("window1");
win.inc:on(EventType.CLICK, function(evt)
win.bar1:set_value(win.bar1.value + 10);
end);
win.dec:on(EventType.CLICK, function(evt)
win.bar1:set_value(win.bar1.value - 10);
end);
Timer.add(function()
if win.bar2.value <= 95 then
win.bar2:set_value(win.bar2.value + 5);
end
return Ret.REPEAT
end, 500)
win.dialog:on(EventType.CLICK, function(evt)
local dlg = Dialog.open("dialog1");
dlg.client.ok:on(EventType.CLICK, function(evt)
dlg:quit(0)
end);
dlg.client.cancel:on(EventType.CLICK, function(evt)
dlg:quit(1)
end);
dlg:modal()
dlg:destroy()
end);
end
application_init()

View File

@ -256,6 +256,14 @@ static int wrap_dialog_create(lua_State* L) {
return lftk_newuserdata(L, ret, "/dialog_t/widget_t", "lftk.dialog_t");
}
static int wrap_dialog_open(lua_State* L) {
widget_t* ret = NULL;
char* name = (char*)luaL_checkstring(L, 1);
ret = (widget_t*)dialog_open(name);
return lftk_newuserdata(L, ret, "/dialog_t/widget_t", "lftk.dialog_t");
}
static int wrap_dialog_set_icon(lua_State* L) {
ret_t ret = 0;
widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t");
@ -331,7 +339,8 @@ static int wrap_dialog_t_get_prop(lua_State* L) {
}
static void dialog_t_init(lua_State* L) {
static const struct luaL_Reg static_funcs[] = {{"create", wrap_dialog_create}, {NULL, NULL}};
static const struct luaL_Reg static_funcs[] = {
{"create", wrap_dialog_create}, {"open", wrap_dialog_open}, {NULL, NULL}};
static const struct luaL_Reg index_funcs[] = {
{"__index", wrap_dialog_t_get_prop}, {"__newindex", wrap_dialog_t_set_prop}, {NULL, NULL}};
@ -439,7 +448,7 @@ static int wrap_event_t_get_prop(lua_State* L) {
return 1;
} else {
printf("%s: not supported %s\n", __func__, name);
return 1;
return 0;
}
}
@ -1013,7 +1022,7 @@ static int wrap_point_t_get_prop(lua_State* L) {
return 1;
} else {
printf("%s: not supported %s\n", __func__, name);
return 1;
return 0;
}
}
@ -1086,7 +1095,7 @@ static int wrap_rect_t_get_prop(lua_State* L) {
return 1;
} else {
printf("%s: not supported %s\n", __func__, name);
return 1;
return 0;
}
}
@ -1128,7 +1137,7 @@ static int wrap_style_t_get_prop(lua_State* L) {
return 1;
} else {
printf("%s: not supported %s\n", __func__, name);
return 1;
return 0;
}
}
@ -1170,7 +1179,7 @@ static int wrap_theme_t_get_prop(lua_State* L) {
return 1;
} else {
printf("%s: not supported %s\n", __func__, name);
return 1;
return 0;
}
}
@ -1735,7 +1744,7 @@ static int wrap_value_t_get_prop(lua_State* L) {
return 1;
} else {
printf("%s: not supported %s\n", __func__, name);
return 1;
return 0;
}
}
@ -2174,6 +2183,7 @@ static const struct luaL_Reg widget_t_member_funcs[] = {
{"set_visible", wrap_widget_set_visible},
{"on", wrap_widget_on},
{"off", wrap_widget_off},
{"on", wrap_widget_on},
{"invalidate", wrap_widget_invalidate},
{"get_prop", wrap_widget_get_prop},
{"set_prop", wrap_widget_set_prop},
@ -2287,8 +2297,12 @@ static int wrap_widget_t_get_prop(lua_State* L) {
} else if (strcmp(name, "parent") == 0) {
return lftk_newuserdata(L, obj->parent, "/widget_t", "lftk.widget_t");
} else {
widget_t* child = widget_lookup(obj, name, FALSE);
if (child != NULL) {
return lftk_newuserdata(L, child, "/widget_t", "lftk.widget_t");
}
printf("%s: not supported %s\n", __func__, name);
return 1;
return 0;
}
}
@ -2361,6 +2375,14 @@ static int wrap_window_create(lua_State* L) {
return lftk_newuserdata(L, ret, "/window_t/widget_t", "lftk.window_t");
}
static int wrap_window_open(lua_State* L) {
widget_t* ret = NULL;
char* name = (char*)luaL_checkstring(L, 1);
ret = (widget_t*)window_open(name);
return lftk_newuserdata(L, ret, "/window_t/widget_t", "lftk.window_t");
}
static const struct luaL_Reg window_t_member_funcs[] = {{NULL, NULL}};
static int wrap_window_t_set_prop(lua_State* L) {
@ -2389,7 +2411,8 @@ static int wrap_window_t_get_prop(lua_State* L) {
}
static void window_t_init(lua_State* L) {
static const struct luaL_Reg static_funcs[] = {{"create", wrap_window_create}, {NULL, NULL}};
static const struct luaL_Reg static_funcs[] = {
{"create", wrap_window_create}, {"open", wrap_window_open}, {NULL, NULL}};
static const struct luaL_Reg index_funcs[] = {
{"__index", wrap_window_t_get_prop}, {"__newindex", wrap_window_t_set_prop}, {NULL, NULL}};

View File

@ -9,7 +9,7 @@ extern void luaL_openlftk(lua_State* L);
int main(int argc, char* argv[]) {
lua_State* L = luaL_newstate();
static uint32_t s_heap_mem[10 * 1024];
const char* lua_file = argc == 2 ? argv[1] : "./demo.lua";
const char* lua_file = argc == 2 ? argv[1] : "./demo2.lua";
luaL_openlibs(L);
luaL_openlftk(L);

View File

@ -117,6 +117,7 @@ widget_t* dialog_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
wstr_init(&(dialog->title), 0);
widget_set_state(widget, WIDGET_STATE_NORMAL);
dialog->client = group_box_create(widget, 0, TITLE_H, widget->w, widget->h - TITLE_H);
widget_set_name(dialog->client, "client");
log_debug("%s\n", __func__);

View File

@ -55,6 +55,16 @@ typedef struct _dialog_t {
*/
widget_t* dialog_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method dialog_open
* @constructor
* Dialog对象ui_loader/ui_builder_default里实现
* @param {char*} name dialog的名称
*
* @return {widget_t*}
*/
/**
* @method dialog_set_icon
*

View File

@ -595,7 +595,7 @@ ret_t widget_off(widget_t* widget, uint32_t id);
/**
* @method widget_child_on
*
* @scriptable custom
* @scriptable no
* @param {widget_t*} widget
* @param {char*} name
* @param {event_type_t} type

View File

@ -50,6 +50,15 @@ typedef struct _window_t {
*/
widget_t* window_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method window_open
* @constructor
* window对象ui_loader/ui_builder_default里实现
* @param {char*} name window的名称
*
* @return {widget_t*}
*/
END_C_DECLS
#endif/*LFTK_WINDOW_H*/

View File

@ -156,3 +156,5 @@ widget_t* window_open(const char* name) {
return builder->root;
}
widget_t* dialog_open(const char* name) { return window_open(name); }

View File

@ -29,6 +29,7 @@ BEGIN_C_DECLS
ui_builder_t* ui_builder_default();
widget_t* window_open(const char* name);
widget_t* dialog_open(const char* name);
END_C_DECLS

17
tools/idl_gen/README.md Normal file
View File

@ -0,0 +1,17 @@
# 脚本绑定代码产生器
运行本目录中的工具需要安装[nodejs](https://nodejs.org/zh-cn/)。
工作原理:**api doc** \-\-> **idl** \-\-> **不同语言的绑定**
## 产生IDL文件
```
node gen_idl.js
```
## 产生lua脚本绑定
```
node gen_lua.js
```

View File

@ -161,7 +161,7 @@ function extractIDL(result, filename, content) {
function genOneFile(result, filename) {
const content = fs.readFileSync(filename).toString();
const name = filename.match(/[a-z|_\d|\.|A-Z]*\/[a-z|_\d|\.|A-Z]*$/)[0];
console.log(filename);
console.log(`process ${filename}`);
extractIDL(result, name, content);
}

View File

@ -162,10 +162,9 @@ function genAll(json) {
} else {
str += ` else if(strcmp(name, "${p.name}") == 0) {\n`;
}
str += ' ';
if (p.readonly) {
str += ` printf("${p.name} is readonly\\n");\n`;
str += ` return 0;\n`;
str += ` return 0;\n`;
} else {
str += genDecl(2, p.type, p.name);
str += ` obj->${p.name} = ${p.name};\n`;
@ -200,8 +199,8 @@ function genAll(json) {
str += `static int wrap_${clsName}_set_prop(lua_State* L) {\n`;
str += genDecl(0, cls.name + '*', "obj");
str += genDecl(1, "const char*", "name");
str += '(void)obj;\n';
str += '(void)name;\n';
str += ' (void)obj;\n';
str += ' (void)name;\n';
let hasSetProps = false;
cls.properties.forEach((m, index) => {
@ -210,19 +209,19 @@ function genAll(json) {
});
if (hasSetProps) {
str += ` else {\n `;
str += ` else {\n`;
}
if (cls.parent) {
str += ` return wrap_${cls.parent}_set_prop(L);\n`;
} else if (hasSetProps) {
str += ` printf("%s: not supported %s\\n", __func__, name);\n`;
str += ` return 0;\n`;
str += ` printf("%s: not supported %s\\n", __func__, name);\n`;
str += ` return 0;\n`;
}
if (hasSetProps) {
str += ` }\n`;
} else {
str += ` printf("%s: not supported %s\\n", __func__, name);\n`;
str += ` return 0;\n`;
str += ` printf("%s: not supported %s\\n", __func__, name);\n`;
str += ` return 0;\n`;
}
str += `}\n\n`;
@ -254,8 +253,14 @@ function genAll(json) {
if (cls.parent) {
str += ` return wrap_${cls.parent}_get_prop(L);\n`;
} else {
if(cls.name === 'widget_t') {
str += ` widget_t* child = widget_lookup(obj, name, FALSE);\n`;
str += ` if(child != NULL) {\n`;
str += ` return lftk_newuserdata(L, child, "/widget_t", "lftk.widget_t");\n`;
str += ` }\n`;
}
str += ` printf("%s: not supported %s\\n", __func__, name);\n`;
str += ` return 1;\n`;
str += ` return 0;\n`;
}
str += ` }\n`;

View File

@ -181,6 +181,17 @@
"isConstructor": true,
"return": "widget_t*"
},
{
"params": [
{
"type": "char*",
"name": "name"
}
],
"name": "dialog_open",
"isConstructor": true,
"return": "widget_t*"
},
{
"params": [
{
@ -1748,6 +1759,29 @@
"isCustom": true,
"return": "ret_t"
},
{
"params": [
{
"type": "widget_t*",
"name": "widget"
},
{
"type": "event_type_t",
"name": "type"
},
{
"type": "event_func_t",
"name": "on_event"
},
{
"type": "void*",
"name": "ctx"
}
],
"name": "widget_on",
"isCustom": true,
"return": "uint32_t"
},
{
"params": [
{
@ -1941,6 +1975,17 @@
"name": "window_create",
"isConstructor": true,
"return": "widget_t*"
},
{
"params": [
{
"type": "char*",
"name": "name"
}
],
"name": "window_open",
"isConstructor": true,
"return": "widget_t*"
}
],
"properties": [],