集成 AWTK 到 iotjs

集成 AWTK 到 iotjs

iotjs 是三星开源的 javascript 物联网开发平台。它为 javascript 应用程序提供了访问硬件、网络、文件系统和异步化的能力,功能类似于 nodejs,但无论是代码体积还是内存需求,iotjs 都要小很多,是用 javascript 开发 iot 设备应用程序的首选。

AWTK 全称 Toolkit AnyWhere,是 ZLG 开发的开源 GUI 引擎,旨在为嵌入式系统、WEB、各种小程序、手机和 PC 打造的通用 GUI 引擎,为用户提供一个功能强大、高效可靠、简单易用、可轻松做出炫酷效果的 GUI 引擎。

用 C 语言来扩展 iotjs 不是太难的事情,但是将 GUI 集成到 iotjs 却是有些麻烦的。主要原因在于 iotjs 有个主循环 (main loop),GUI 自己也有个主循环 (main loop),两者不同并存,只能选一个。这里 AWTK 为例,介绍一下如何将 GUI 集成到 iotjs 中,这对将 GUI 集成到 nodejs 也是有参考价值。

一、以谁为主

在集成 AWTK 到 iotjs 时,我选择了以 iotjs 的主循环为主。这并不是唯一的正确方案,做这个选择的主要原因有:

  • AWTK 作为 iotjs 的模块,保持 iotjs 本身的开发方式。

  • 避免修改 iotjs。iotjs 对我来说是第三方模块,修改第三方模块,会增加后期的维护成本。

我们把 AWTK 主循环的一次循环提取成一个 step,然后把它放到 iotjs 的定时器中,每隔 16 毫秒(最大 60FPS) 调用一次,这样可以模拟 GUI 的主循环了。

const char* s_step_script = "\
(function() { \
  var awtkStepId = 0;\
  function awtkStep() {\
    if(!awtk_main_loop_step()) {\
      clearInterval(awtkStepId);\
      console.log(\"awtk quit\");\
      awtkStepId = 0;\
    }\
  }\
  awtkStepId = setInterval(awtkStep, 16);\
}())";

JS_FUNCTION(wrap_awtk_main_loop_step) {
  bool_t ret = FALSE;
  main_loop_t* loop = main_loop();

  if(loop != NULL) {
    main_loop_step(loop);

    ret = !(loop->app_quited);
    if(loop->app_quited) {
      tk_exit();
    }
  }

  return jerry_create_number(ret);
}

值得注意的是,这个定时器一定要放在 javascript 里去调用。 开始我用了 libuv 原生的定时器来实现,代码简洁而且高效,但是应用程序退出时,iotjs 就会崩掉,原因是 iotjs 认为所有的定时器都是 javascript 里的,而 javascripte 里的定时器是在原生定时器基础上包装而成,在应用程序退出时做了一些额外的释放工作。

二、模态对话框

模态对话框会再次调用主循环的 run,直到对话框关闭。这个时候需要在 GUI 主循环中调用 iotjs 的主循环。但是 iotjs 的循环是 libuv 主循环的基础上包装了一层,而且不适合外面再次调用,所以我仿造 iotjs 实现了一个:

static ret_t  main_loop_iotjs_run(main_loop_t* loop) {
  ret_t ret = RET_OK;
  iotjs_environment_t* env = iotjs_environment_get();

  if (!iotjs_environment_is_exiting(env)) {
    bool more = 0;
    do {
      more = uv_run(iotjs_environment_loop(env), UV_RUN_ONCE);
      more |= iotjs_process_next_tick();

      jerry_value_t ret_val = jerry_run_all_enqueued_jobs();
      if (jerry_value_is_error(ret_val)) {
        ret_val = jerry_get_value_from_error(ret_val, true);
        iotjs_uncaught_exception(ret_val);
        jerry_release_value(ret_val);
      }

      if (more == false) {
        more = uv_loop_alive(iotjs_environment_loop(env));
      }

      if(!(loop->running)) {
        break;
      }
    } while (more && !iotjs_environment_is_exiting(env));
  }

  return ret;

!(loop->running) 表示模态对话框已经退出,可以回调上一级主循环了。

三、GUI 需要提供 Jerryscript 的绑定

要将 GUI 集成到 iotjs,GUI 必须要把对外提供的 AIP 全部绑定到 jerryscript。这个对 AWTK 来说只是举手之劳的事情,AWTK 通过提取注释来生成 IDL,再根据 IDL 来生成各种语言的绑定,这让绑定工作变得轻松,同时也降低了后期的维护成本。

AWTK-JS 这个项目提供了对 jerryscript 的绑定,我们把它编译成一个库,即可在 AWTK-iotjs 中使用了。

static int gui_app_start(int32_t lcd_w, int32_t lcd_h) {
  tk_init(lcd_w, lcd_h, APP_SIMULATOR, NULL, APP_ASSETS_ROOT);

  assets_init();
  awtk_js_init();
  main_loop()->running = TRUE;
  awtk_jerryscript_eval(AWTK_JS_FILE);

  tk_main_loop_run();

  return 0;
}

在启动 GUI 时,调用 awtk_js_init 初始化 AWTK 的 jerryscript 绑定,调用 awtk_jerryscript_eval 预先加载 awtk.js 文件。

完整例子请参考:https://github.com/zlgopen/awtk-iotjs

转载于:https://my.oschina.net/u/3979680/blog/3060322

AWTK开发手册-AWTK开发实践指南-中文手册.pdf AWTK = Toolkit AnyWhere 随着手机、智能手表等便携式设备的普及,用户对 GUI 的要求越来越高,嵌入式系统对高性能、高可靠性、低功耗、美观炫酷的 GUI 的需求也越来越迫切,ZLG开源 GUI 引擎 AWTK 应运而生。AWTK 全称为 Toolkit AnyWhere,是 ZLG 倾心打造的一套基于 C 语言开发的 GUI 框架。旨在为用户提供一个功能强大、高效可靠、简单易用、可轻松做出炫酷效果的 GUI 引擎,并支持跨平台同步开发,一次编程,终生使用。 最终目标: 支持开发嵌入式软件。 支持开发Linux应用程序。 支持开发MacOS应用程序。 支持开发Windows应用程序。 支持开发Android应用程序。 支持开发iOS应用程序。 支持开发2D游戏。 其主要特色有: 小巧。在精简配置下,不依赖第三方软件包,仅需要32K RAM + 256K FLASH即可开发一些简单的图形应用程序。 高效。采用脏矩形裁剪算法,每次只绘制和更新变化的部分,极大提高运行效率和能源利用率。 稳定。通过良好的架构设计和编程风格、单元测试、动态(valgrind)检查和Code Review保证其运行的稳定性。 丰富的GUI组件。提供窗口、对话框和各种常用的组件(用户可以配置自己需要的组件,降低对运行环境的要求)。 支持多种字体格式。内置位图字体(并提供转换工具),也可以使用stb_truetype或freetype加载ttf字体。 支持多种图片格式。内置位图图片(并提供转换工具),也可以使用stb_image加载png/jpg等格式的图片。 紧凑的二进制界面描述格式。可以手工编辑的XML格式的界面描述文件,也可以使用Qt Designer设计界面,然后转换成紧凑的二进制界面描述格式,提高运行效率,减小内存开销。 支持主题并采用紧凑的二进制格式。开发时使用XML格式描述主题,然后转换成紧凑的二进制格式,提高运行效率,减小内存开销。 支持裸系统,无需OS和文件系统。字体、图片、主题和界面描述数据都编译到代码中,以常量数据的形式存放,运行时无需加载到内存。 内置nanovg实现高质量的矢量动画,并支持SVG矢量图。 支持窗口动画、控件动画、滑动动画和高清LCD等现代GUI常见特性。 支持国际化(Unicode、字符串翻译和输入法等)。 可移植。支持移植到各种RTOS和嵌入式Linux系统,并通过SDL在各种流行的PC/手机系统上运行。 脚本化。从API注释中提取API的描述信息,通过这些信息可以自动生成各种脚本的绑定代码。 支持硬件2D加速(目前支持STM32的DMA2D和NXP的PXP)和GPU加速(OpenGL/OpenGLES/DirectX/Metal),充分挖掘硬件潜能。 丰富的文档和示例代码。 采用LGPL协议开源发布,在商业软件中使用时无需付费。 目前核心功能已经完成,内部开始在实际项目中使用了,欢迎有兴趣的朋友评估和尝试,期待您的反馈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值