编译 JavaScript 引擎 QuickJS 到 Andro

2021-05-23  本文已影响0人  ImWiki

QuickJS 是一个小型并且可嵌入的 Javascript 引擎,它支持ES2020规范,包括模块,异步生成器和代理器。编译下来只有几百KB,相比 V8 需要几MB小得多,在对大小有要求的嵌入式设备来说是 V8 一个不错的替代品。国人写了一份中文文档可以参考。

在Mac OS编译QuickJS

# 下载代码
git clone https://github.com/bellard/quickjs
cd quickjs
# 编译
make

执行完 make 后,就会在根目录生成了qjs可执行文件,就可以进行测试

./qjs examples/hello.js

对象介绍

在Android编译QuickJS

创建JNI项目

这一步就不介绍了,自行使用Android Studio创建一个JNI的项目。

由于QuickJS使用了一些高版本的API,所以 minSdkVersion 必须大于18。

把QuickJS代码放到项目中

需要把QuickJS 的代码下载到main/cpp/quickjs。
文件结构如下:

main
├── AndroidManifest.xml
├── cpp
│   ├── CMakeLists.txt
│   ├── quickjs-jni.cpp
│   └── quickjs
│       ├── CMakeLists.txt
│       └── quickjs
│           ├── VERSION
│           ├── cutils.c
│           ├── cutils.h
│           ├── libbf.c
│           ├── libbf.h
│           ├── libregexp.c
│           ├── libregexp.h
│           ├── libunicode.c
│           ├── libunicode.h
│           ├── quickjs.c
│           └── quickjs.h
└── java
    └── com/quickjs/android/QuickJS.java

在 quickjs 目录下创建一个CMakeLists.txt文件,文件内容如下:

cmake_minimum_required(VERSION 3.10.2)
project(quickjs CXX)
include_directories(quickjs)
set(SOURCE_DIR
        quickjs/cutils.c
        quickjs/libbf.c
        quickjs/libregexp.c
        quickjs/libunicode.c
        quickjs/quickjs.c
        )

file(STRINGS "quickjs/VERSION" CONFIG_VERSION)
add_definitions(-DCONFIG_VERSION="${CONFIG_VERSION}")
add_definitions(-DCONFIG_BIGNUM)
add_definitions(-D_GNU_SOURCE)
add_definitions(-DCONFIG_CC="gcc")
add_definitions(-DCONFIG_PREFIX="/usr/local")
add_library(
        ${PROJECT_NAME}
        SHARED
        ${SOURCE_DIR}
)
target_include_directories(${PROJECT_NAME} PUBLIC .)

把cpp/CMakeLists.txt修改成

cmake_minimum_required(VERSION 3.10.2)
project("quickjs-android")
add_subdirectory(./quickjs)
add_library(
        ${PROJECT_NAME}
        SHARED
        quickjs-jni.cpp)
find_library(
        log-lib
        log)
target_link_libraries(
        ${PROJECT_NAME}
        ${log-lib}
        quickjs
)

QuickJS.java内容如下:

package com.quickjs.android;

public class QuickJS {
    public static native int executeIntegerScript(String source,String fileName);
}

quickjs-jni.cpp 内容如下:

#include <jni.h>
#include <string>
#include <quickjs/quickjs.h>


extern "C"
JNIEXPORT jint JNICALL
Java_com_quickjs_android_QuickJS_executeIntegerScript(JNIEnv *env, jclass clazz, jstring jCode,
                                                      jstring jFileName) {
    JSRuntime *jsRuntime = JS_NewRuntime();
    JSContext *context = JS_NewContext(jsRuntime);
    const char *code = env->GetStringUTFChars(jCode, NULL);
    const int code_length = env->GetStringUTFLength(jCode);
    const char *file_name = env->GetStringUTFChars(jFileName, NULL);
    int flags = 0;
    JSValue val = JS_Eval(context, code, (size_t) code_length, file_name, flags);
    int result = JS_VALUE_GET_INT(val);
    return result;
}
测试
    protected void test() {
        int result = QuickJS.executeIntegerScript("var a = 2+2;\n a;", "file.js");
        Log.e("quickjs", String.valueOf(result));
    }

    static {
        System.loadLibrary("quickjs");
        System.loadLibrary("quickjs-android");
    }

就会输出结果:4

项目代码

https://github.com/taoweiji/quickjs-android

总结

编译下来armeabi-v7a的so文件仅仅380KB,相比Google V8引擎的7MB小得多。上面只是简单的示例,需要完整使用 QuickJS 功能还需要大量的适配工作,推荐使用 quickjs-android

上一篇下一篇

猜你喜欢

热点阅读