編譯 JavaScript 引擎 QuickJS 到 Android 教程

QuickJS 是一個小型并且可嵌入的 Javascript 引擎,它支持ES2020規(guī)范,包括模塊,異步生成器和代理器。編譯下來只有幾百KB,相比 V8 需要幾MB小得多,在對大小有要求的嵌入式設(shè)備來說是 V8 一個不錯的替代品。國人寫了一份中文文檔可以參考。

在Mac OS編譯QuickJS

# 下載代碼
git clone https://github.com/bellard/quickjs
cd quickjs
# 編譯
make

執(zhí)行完 make 后,就會在根目錄生成了qjs可執(zhí)行文件,就可以進(jìn)行測試

./qjs examples/hello.js

對象介紹

  • JSRuntime:JavaScript 的運(yùn)行時,可以創(chuàng)建多個運(yùn)行時,但是不同的運(yùn)行時不能共享對象。
  • JSContext:一個 JSRuntime 可以創(chuàng)建多個 JSContext,同一個 JSRuntime 下的 JSContext 可以共享對象。
  • JSValue:JavaScript 的變量及 Function 等。

在Android編譯QuickJS

創(chuàng)建JNI項目

這一步就不介紹了,自行使用Android Studio創(chuàng)建一個JNI的項目。

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

把QuickJS代碼放到項目中

需要把QuickJS 的代碼下載到main/cpp/quickjs。
文件結(jié)構(gòu)如下:

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 目錄下創(chuàng)建一個CMakeLists.txt文件,文件內(nèi)容如下:

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內(nèi)容如下:

package com.quickjs.android;

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

quickjs-jni.cpp 內(nèi)容如下:

#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");
    }

就會輸出結(jié)果:4

項目代碼

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

總結(jié)

編譯下來armeabi-v7a的so文件僅僅380KB,相比Google V8引擎的7MB小得多。上面只是簡單的示例,需要完整使用 QuickJS 功能還需要大量的適配工作,推薦使用 quickjs-android 。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容