Duktape
Duktape是一个嵌入式Javascript引擎,专注于可移植性和低空间占用。
Duktape易于集成到C/C++项目中:将duktape.c
,
duktape.h
,和duk_config.h
添加到您的构建项目中,并使用Duktape API实现C代码与Ecmascript函数的双向调用。
主要特性
- 可嵌入,可移植,低占用:可运行于只有192kB闪存空间(flash)以及64kB系统内存(RAM)的平台上
- 兼容 Ecmascript E5/E5.1 ,一些语义规范更新自 ES2015+
- 部分支持 Ecmascript 2015 (E6) 和 Ecmascript 2016 (E7),参见 Post-ES5 特性
- 支持 ES2015 TypedArray 和 Node.js Buffer 绑定
- 内置调试器
- 内置正则表达式引擎
- 内置Unicode支持
- 最小限度的平台依赖
- 整合了引用计数和标记-清除算法(mark-and-sweep)垃圾收集机制
- 协程支持
- 属性虚拟化中使用了Ecmascript E6 Proxy对象的一个子集
- 以字节码转储(dump)/加载的方式来缓存已编译的函数
- 发布版中包含一个日志框架和基于CommonJS的模块加载实现等
- 采用 MIT 的自由许可证
代码空间和内存(RAM)占用
x86 默认 | x86 低端内存 | x86 全低端内存 | |
代码占用空间 | 170kB | 150kB | 200kB |
启动内存 | 68kB | 35kB | 2.3kB |
请参阅 GCC选项 以最小化代码占用空间。全 低端内存 使用了“指针压缩”和基于ROM的字符串/对象。基于ROM的字符串/对象也可以在其他非低端内存选项中使用。
当前状态
- 稳定
技术支持
- Duktape Wiki: wiki.duktape.org
- 用户问答社区:Stack Overflow 上的 duktape 标签
- Bug和功能需求: GitHub issues
- 综合讨论区:
chat.freenode.net
上的 IRC 频道#duktape
(webchat)
一些使用Duktape的项目
参见: 使用Duktape的项目.
如果你的项目中使用了Duktape,可以发电子邮件通知我们或开一个GitHub issue来将它添加到列表中。
类似的引擎
有多个Javascript引擎与Duktape有类似的功能定位,它们至少包括以下几个:
- Espruino (MPL v2.0)
- JerryScript (Apache License v2.0)
- MuJS (Affero GPL)
- quad-wheel (MIT License)
- tiny-js (MIT license)
- v7 (GPL v2.0)
另请参见 ECMAScript引擎列表。
1 添加到构建
(有关更详细的介绍,请参阅 入门指南 。)
将Duktape C源代码和头文件添加到您的构建项目中。它可在任意构建系统中使用。发布的版本中已包含一个Makefile示例供参考。下面是最简单的例子:
$ gcc -std=c99 -otest test.c duktape.c -lm
$ ./test
1+2=3
要 自定义 Duktape 配置信息 ,
在这里禁用Ecmascript 6 Proxy
对象支持:
$ python2 duktape-2.0.0/tools/configure.py --output-directory src-duktape \ -UDUK_USE_ES6_PROXY $ ls src-duktape/ duk_config.h duk_source_meta.json duktape.c duktape.h $ gcc -std=c99 -otest -Isrc-duktape \ test.c src-duktape/duktape.c -lm $ ./test 1+2=3
2 初始化上下文context
在你程序中的任意位置初始化和使用Duktape:
/* test.c */ #include <stdio.h> #include "duktape.h" int main(int argc, char *argv[]) { duk_context *ctx = duk_create_heap_default(); duk_eval_string(ctx, "1+2"); printf("1+2=%d\n", (int) duk_get_int(ctx, -1)); duk_destroy_heap(ctx); return 0; }
3 添加C函数绑定
要在Ecmascript代码中调用C函数,首先得声明C函数:
/* 作为一个嵌入式引擎,Duktape 默认不提供I/O绑定。 * 这里是简单的只有一个参数的 print() 函数。 */ static duk_ret_t native_print(duk_context *ctx) { printf("%s\n", duk_to_string(ctx, 0)); return 0; /* no return value (= undefined) */ } /* Adder: add argument values. */ static duk_ret_t native_adder(duk_context *ctx) { int i; int n = duk_get_top(ctx); /* #args */ double res = 0.0; for (i = 0; i < n; i++) { res += duk_to_number(ctx, i); } duk_push_number(ctx, res); return 1; /* one return value */ }
注册C函数到全局对象:
duk_push_c_function(ctx, native_print, 1 /*nargs*/); duk_put_global_string(ctx, "print"); duk_push_c_function(ctx, native_adder, DUK_VARARGS); duk_put_global_string(ctx, "adder");
之后就可以在Ecmascript代码中调用C函数了:
duk_eval_string_noresult(ctx, "print('2+3=' + adder(2, 3));");