
以前嵌入脚本首选Lua,但有些年头没有用Lua了,语法也快忘记光了,这些年倒是对 JavaScript 语法愈发熟悉了,于是想看看有没有小巧的 JavaScript 引擎,可以嵌入到 C++程序中使用。嘿,还真有。花时间研究了下 JerryScript 库,也顺手给 JerryScript 提交了几个 PR 被采纳了,有幸成为顶级项目的 Contributor(就是玩儿 ^_^)。

JerryScript 是一个轻量级的 JavaScript 引擎,资源占用极少,它可以运行在资源受限制的设备上,如:
- 只有几 KB RAM 能运行引擎的设备(<64 KB RAM)
 
- 只能为代码引擎提供有限 ROM 空间的设备(<200 KB ROM)
 
JerryScript 使用 C 语言开发,跨平台。
为什么没有选择 QuickJS?
说起轻量级的 JavaScript 引擎,很多人都会想到 QuickJS。的确,我一开始也选择了 QuickJS,但一番研究之后,发现 QuickJS 在 Windows 环境下编译实在是不太友好,不仅需要安装 Mingw64,而且修改编译选项也不方便。可能是我能力的问题吧,我还未找到将 QuickJS 编译成 MT 运行库的静态库的方法。
一个库在编译方面做得都不够友好,何况 Windows 也不是冷门的系统,那就没必要委屈自己了,毕竟还有其他的选择。
反观 JerryScript,使用 CMake 进行构建,不需要进行任何修改,一路畅通。
快速上手
JerryScript 的接口比较简洁, 而且官方已经提供了丰富的示例,示例地址如下:
https://jerryscript.net/api-example/
下面是一个简单的示例,演示了如何暴露 C++ 的函数给 JS 进行调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
   | #include <stdio.h> #include "jerryscript.h"
 
  static jerry_value_t print_handler(     const jerry_call_info_t* call_info_p,     const jerry_value_t arguments[],     const jerry_length_t argument_count) {          printf("Print handler was called\n");
           return jerry_undefined(); }
  int main(void) {     const jerry_char_t script[] = "print ();";     const jerry_length_t script_size = sizeof(script) - 1;
           jerry_init(JERRY_INIT_EMPTY);
                {         jerry_value_t global_object = jerry_current_realm();         jerry_value_t property_name_print = jerry_string_sz("print");         jerry_value_t property_value_func = jerry_function_external(print_handler);         jerry_value_t set_result = jerry_object_set(global_object, property_name_print, property_value_func);
                   if (jerry_value_is_exception(set_result)) {             printf("Failed to add the 'print' property\n");         }
          jerry_value_free(set_result);         jerry_value_free(property_value_func);         jerry_value_free(property_name_print);         jerry_value_free(global_object);     }
      jerry_value_t parsed_code = jerry_parse(script, script_size, NULL);     if (!jerry_value_is_exception(parsed_code))     {                  jerry_value_t ret_value = jerry_run(parsed_code);
                   jerry_value_free(ret_value);     }
      jerry_value_free(parsed_code);     jerry_cleanup();
      return 0; }
   |