mirror of
https://github.com/wgh136/flutter_qjs.git
synced 2025-09-28 05:47:24 +00:00
android type wrapper
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
set(JNI_LIB_NAME libjsengine)
|
||||
set(QUICK_JS_LIB_DIR ../../../../cxx)
|
||||
set(QUICK_JS_LIB_DIR ../../../../cxx/quickjspp)
|
||||
|
||||
|
||||
# Creates and names a library, sets it as either STATIC
|
||||
|
195
android/src/main/jni/java_js_wrapper.hpp
Normal file
195
android/src/main/jni/java_js_wrapper.hpp
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: ekibun
|
||||
* @Date: 2020-08-16 11:08:23
|
||||
* @LastEditors: ekibun
|
||||
* @LastEditTime: 2020-08-16 19:51:11
|
||||
*/
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "jni_helper.hpp"
|
||||
#include <android/log.h>
|
||||
#include "../../../../cxx/js_engine.hpp"
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<qjs::Value>
|
||||
{
|
||||
std::size_t operator()(const qjs::Value &key) const
|
||||
{
|
||||
return std::hash<std::string>()((std::string)key);
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
namespace qjs
|
||||
{
|
||||
|
||||
JSValue javaToJs(JSContext *ctx, JNIEnv *env, jobject val, std::unordered_map<jobject, JSValue> cache = std::unordered_map<jobject, JSValue>())
|
||||
{
|
||||
if (val == nullptr)
|
||||
return JS_UNDEFINED;
|
||||
if (cache.find(val) != cache.end())
|
||||
return cache[val];
|
||||
jclass objclass = env->GetObjectClass(val);
|
||||
jclass classclass = env->GetObjectClass((jobject)objclass);
|
||||
jmethodID mid = env->GetMethodID(classclass, "getName", "()Ljava/lang/String;");
|
||||
jobject clsObj = env->CallObjectMethod(objclass, mid);
|
||||
std::string className(env->GetStringUTFChars((jstring)clsObj, 0));
|
||||
__android_log_print(ANDROID_LOG_DEBUG, "class", "class: %s", className.c_str());
|
||||
if (className.compare("[B") == 0)
|
||||
{
|
||||
jsize len = env->GetArrayLength((jbyteArray)val);
|
||||
return JS_NewArrayBufferCopy(ctx, (uint8_t *)env->GetByteArrayElements((jbyteArray)val, 0), len);
|
||||
}
|
||||
else if (className.compare("java.lang.Boolean") == 0)
|
||||
{
|
||||
jmethodID getVal = env->GetMethodID(objclass, "booleanValue", "()Z");
|
||||
return JS_NewBool(ctx, env->CallBooleanMethod(val, getVal));
|
||||
}
|
||||
else if (className.compare("java.lang.Integer") == 0)
|
||||
{
|
||||
jmethodID getVal = env->GetMethodID(objclass, "intValue", "()I");
|
||||
return JS_NewInt32(ctx, env->CallIntMethod(val, getVal));
|
||||
}
|
||||
else if (className.compare("java.lang.Long") == 0)
|
||||
{
|
||||
jmethodID getVal = env->GetMethodID(objclass, "longValue", "()J");
|
||||
return JS_NewInt64(ctx, env->CallLongMethod(val, getVal));
|
||||
}
|
||||
else if (className.compare("java.lang.Double") == 0)
|
||||
{
|
||||
jmethodID getVal = env->GetMethodID(objclass, "doubleValue", "()D");
|
||||
return JS_NewFloat64(ctx, env->CallDoubleMethod(val, getVal));
|
||||
}
|
||||
else if (className.compare("java.lang.String") == 0)
|
||||
{
|
||||
return JS_NewString(ctx, env->GetStringUTFChars((jstring)val, 0));
|
||||
}
|
||||
else if (className.compare("java.util.ArrayList") == 0)
|
||||
{
|
||||
jobjectArray list = jniToArray(env, val);
|
||||
jsize size = env->GetArrayLength(list);
|
||||
JSValue array = JS_NewArray(ctx);
|
||||
cache[val] = array;
|
||||
for (uint32_t i = 0; i < size; i++)
|
||||
JS_DefinePropertyValue(
|
||||
ctx, array, JS_NewAtomUInt32(ctx, i),
|
||||
javaToJs(ctx, env, env->GetObjectArrayElement(list, i), cache),
|
||||
JS_PROP_C_W_E);
|
||||
return array;
|
||||
}
|
||||
else if (className.compare("java.util.HashMap") == 0)
|
||||
{
|
||||
// 获取HashMap类entrySet()方法ID
|
||||
jmethodID entrySetMID = env->GetMethodID(objclass, "entrySet", "()Ljava/util/Set;");
|
||||
// 调用entrySet()方法获取Set对象
|
||||
jobject setObj = env->CallObjectMethod(val, entrySetMID);
|
||||
// 获取Set类中iterator()方法ID
|
||||
jclass setClass = env->FindClass("java/util/Set");
|
||||
jmethodID iteratorMID = env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
|
||||
// 调用iterator()方法获取Iterator对象
|
||||
jobject iteratorObj = env->CallObjectMethod(setObj, iteratorMID);
|
||||
// 获取Iterator类中hasNext()方法ID
|
||||
// 用于while循环判断HashMap中是否还有数据
|
||||
jclass iteratorClass = env->FindClass("java/util/Iterator");
|
||||
jmethodID hasNextMID = env->GetMethodID(iteratorClass, "hasNext", "()Z");
|
||||
// 获取Iterator类中next()方法ID
|
||||
// 用于读取HashMap中的每一条数据
|
||||
jmethodID nextMID = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
|
||||
// 获取Map.Entry类中getKey()和getValue()的方法ID
|
||||
// 用于读取“K-V”键值对,注意:内部类使用$符号表示
|
||||
jclass entryClass = env->FindClass("java/util/Map$Entry");
|
||||
jmethodID getKeyMID = env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;");
|
||||
jmethodID getValueMID = env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;");
|
||||
// JSObject
|
||||
JSValue obj = JS_NewObject(ctx);
|
||||
cache[val] = obj;
|
||||
// 循环检测HashMap中是否还有数据
|
||||
while (env->CallBooleanMethod(iteratorObj, hasNextMID))
|
||||
{
|
||||
// 读取一条数据
|
||||
jobject entryObj = env->CallObjectMethod(iteratorObj, nextMID);
|
||||
JS_DefinePropertyValue(
|
||||
ctx, obj, JS_ValueToAtom(ctx, javaToJs(ctx, env, env->CallObjectMethod(entryObj, getKeyMID), cache)),
|
||||
javaToJs(ctx, env, env->CallObjectMethod(entryObj, getValueMID), cache),
|
||||
JS_PROP_C_W_E);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
jobject jsToJava(JNIEnv *env, qjs::Value val, std::unordered_map<Value, jobject> cache = std::unordered_map<Value, jobject>())
|
||||
{
|
||||
if (cache.find(val) != cache.end())
|
||||
return cache[val];
|
||||
if (JS_IsBool(val.v))
|
||||
return jniWrapPrimity<jboolean>(env, (bool)val);
|
||||
{
|
||||
int tag = JS_VALUE_GET_TAG(val.v);
|
||||
if(tag == JS_TAG_INT) {
|
||||
return jniWrapPrimity<jlong>(env, (int64_t)val);
|
||||
} else if (JS_TAG_IS_FLOAT64(tag)) {
|
||||
return jniWrapPrimity<jdouble>(env, (double)val);
|
||||
}
|
||||
}
|
||||
if (JS_IsString(val.v))
|
||||
return env->NewStringUTF(((std::string)val).c_str());
|
||||
{
|
||||
size_t size;
|
||||
uint8_t *buf = JS_GetArrayBuffer(val.ctx, &size, val.v);
|
||||
if (buf)
|
||||
{
|
||||
jbyteArray arr = env->NewByteArray(size);
|
||||
env->SetByteArrayRegion(arr, 0, size, (int8_t *)buf);
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
if (JS_IsUndefined(val.v) || JS_IsNull(val.v) || JS_IsUninitialized(val.v))
|
||||
return nullptr;
|
||||
if (JS_IsObject(val.v))
|
||||
{
|
||||
if (JS_IsFunction(val.ctx, val.v))
|
||||
{
|
||||
std::map<jobject, jobject> retMap;
|
||||
retMap[env->NewStringUTF("__js_function__")] = jniWrapPrimity<jlong>(env, (int64_t) new JSValue{JS_DupValue(val.ctx, val.v)});
|
||||
return jniWrapMap(env, retMap);
|
||||
}
|
||||
else if (JS_IsArray(val.ctx, val.v) > 0)
|
||||
{
|
||||
uint32_t arrlen = (uint32_t)val["length"];
|
||||
jclass class_arraylist = env->FindClass("java/util/ArrayList");
|
||||
jmethodID arraylist_init = env->GetMethodID(class_arraylist, "<init>", "()V");
|
||||
jobject list = env->NewObject(class_arraylist, arraylist_init);
|
||||
jmethodID arraylist_add = env->GetMethodID(class_arraylist, "add", "(Ljava/lang/Object;)Z");
|
||||
for (uint32_t i = 0; i < arrlen; i++)
|
||||
{
|
||||
env->CallBooleanMethod(list, arraylist_add, jsToJava(env, val[i], cache));
|
||||
}
|
||||
cache[val] = list;
|
||||
return list;
|
||||
}
|
||||
else
|
||||
{
|
||||
qjs::JSPropertyEnum *ptab;
|
||||
uint32_t plen;
|
||||
if (JS_GetOwnPropertyNames(val.ctx, &ptab, &plen, val.v, -1))
|
||||
return nullptr;
|
||||
std::map<jobject, jobject> retMap;
|
||||
for (uint32_t i = 0; i < plen; i++)
|
||||
{
|
||||
retMap[jsToJava(env, {val.ctx, JS_AtomToValue(val.ctx, ptab[i].atom)}, cache)] =
|
||||
jsToJava(env, {val.ctx, JS_GetProperty(val.ctx, val.v, ptab[i].atom)}, cache);
|
||||
JS_FreeAtom(val.ctx, ptab[i].atom);
|
||||
}
|
||||
js_free(val.ctx, ptab);
|
||||
jobject ret = jniWrapMap(env, retMap);
|
||||
cache[val] = ret;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace qjs
|
62
android/src/main/jni/jni_helper.hpp
Normal file
62
android/src/main/jni/jni_helper.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: ekibun
|
||||
* @Date: 2020-08-16 13:20:03
|
||||
* @LastEditors: ekibun
|
||||
* @LastEditTime: 2020-08-16 17:56:52
|
||||
*/
|
||||
#include <jni.h>
|
||||
#include <map>
|
||||
|
||||
jclass jniInstanceOf(JNIEnv *env, jobject obj, const char *className)
|
||||
{
|
||||
jclass jclazz = env->FindClass(className);
|
||||
return env->IsInstanceOf(obj, jclazz) ? jclazz : nullptr;
|
||||
}
|
||||
|
||||
jobjectArray jniToArray(JNIEnv *env, jobject obj)
|
||||
{
|
||||
jmethodID mToArray = env->GetMethodID(env->GetObjectClass(obj), "toArray", "()[Ljava/lang/Object;");
|
||||
return (jobjectArray)env->CallObjectMethod(obj, mToArray);
|
||||
}
|
||||
|
||||
jobject jniWrapMap(JNIEnv *env, std::map<jobject, jobject> val)
|
||||
{
|
||||
jclass class_hashmap = env->FindClass("java/util/HashMap");
|
||||
jmethodID hashmap_init = env->GetMethodID(class_hashmap, "<init>", "()V");
|
||||
jobject map = env->NewObject(class_hashmap, hashmap_init);
|
||||
jmethodID hashMap_put = env->GetMethodID(class_hashmap, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto it = val.begin(); it != val.end(); ++it)
|
||||
{
|
||||
env->CallObjectMethod(map, hashMap_put, it->first, it->second);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
jobject jniWrapPrimity(JNIEnv *env, T obj);
|
||||
|
||||
template <>
|
||||
jobject jniWrapPrimity(JNIEnv *env, jlong obj)
|
||||
{
|
||||
jclass jclazz = env->FindClass("java/lang/Long");
|
||||
jmethodID jmethod = env->GetMethodID(jclazz, "<init>", "(J)V");
|
||||
return env->NewObject(jclazz, jmethod, obj);
|
||||
}
|
||||
|
||||
template <>
|
||||
jobject jniWrapPrimity(JNIEnv *env, jboolean obj)
|
||||
{
|
||||
// TODO see https://github.com/flutter/flutter/issues/45066
|
||||
std::map<jobject, jobject> retMap;
|
||||
retMap[env->NewStringUTF("__js_boolean__")] = jniWrapPrimity<jlong>(env, (int64_t)obj);
|
||||
return jniWrapMap(env, retMap);
|
||||
}
|
||||
|
||||
template <>
|
||||
jobject jniWrapPrimity(JNIEnv *env, jdouble obj)
|
||||
{
|
||||
jclass jclazz = env->FindClass("java/lang/Double");
|
||||
jmethodID jmethod = env->GetMethodID(jclazz, "<init>", "(D)V");
|
||||
return env->NewObject(jclazz, jmethod, obj);
|
||||
}
|
@@ -3,13 +3,9 @@
|
||||
* @Author: ekibun
|
||||
* @Date: 2020-08-09 18:16:11
|
||||
* @LastEditors: ekibun
|
||||
* @LastEditTime: 2020-08-12 23:37:28
|
||||
* @LastEditTime: 2020-08-16 19:00:06
|
||||
*/
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
#include "../../../../cxx/js_engine.hpp"
|
||||
|
||||
qjs::Engine *engine = nullptr;
|
||||
#include "java_js_wrapper.hpp"
|
||||
|
||||
JNIEnv *getEnv(JavaVM *gJvm)
|
||||
{
|
||||
@@ -26,48 +22,41 @@ JNIEnv *getEnv(JavaVM *gJvm)
|
||||
return env;
|
||||
}
|
||||
|
||||
void jniResultResolve(JavaVM *jvm, jobject result, std::string data)
|
||||
void jniResultResolve(JNIEnv *env, jobject result, jobject data)
|
||||
{
|
||||
JNIEnv *env = getEnv(jvm);
|
||||
jclass jclazz = env->GetObjectClass(result);
|
||||
jmethodID jmethod = env->GetMethodID(jclazz, "success", "(Ljava/lang/String;)V");
|
||||
jstring jdata = env->NewStringUTF(data.c_str());
|
||||
env->CallVoidMethod(result, jmethod, jdata);
|
||||
env->DeleteLocalRef(jdata);
|
||||
jmethodID jmethod = env->GetMethodID(jclazz, "success", "(Ljava/lang/Object;)V");
|
||||
env->CallVoidMethod(result, jmethod, data);
|
||||
env->DeleteLocalRef(data);
|
||||
env->DeleteGlobalRef(result);
|
||||
jvm->DetachCurrentThread();
|
||||
}
|
||||
|
||||
void jniResultReject(JavaVM *jvm, jobject result, std::string reason)
|
||||
void jniResultReject(JNIEnv *env, jobject result, std::string reason)
|
||||
{
|
||||
JNIEnv *env = getEnv(jvm);
|
||||
jclass jclazz = env->GetObjectClass(result);
|
||||
jmethodID jmethod = env->GetMethodID(jclazz, "error", "(Ljava/lang/String;)V");
|
||||
jstring jreason = env->NewStringUTF(reason.c_str());
|
||||
env->CallVoidMethod(result, jmethod, jreason);
|
||||
env->DeleteLocalRef(jreason);
|
||||
env->DeleteGlobalRef(result);
|
||||
jvm->DetachCurrentThread();
|
||||
}
|
||||
|
||||
void jniChannelInvoke(JavaVM *jvm, jobject channel, std::promise<qjs::JSFutureReturn> *promise, std::string method, std::string argv)
|
||||
void jniChannelInvoke(JNIEnv *env, jobject channel, std::promise<qjs::JSFutureReturn> *promise, std::string method, qjs::Value args, qjs::Engine *engine)
|
||||
{
|
||||
JNIEnv *env = nullptr;
|
||||
jvm->GetEnv((void **)&env, JNI_VERSION_1_2);
|
||||
jvm->AttachCurrentThread(&env, NULL);
|
||||
jclass jclazz = env->GetObjectClass(channel);
|
||||
jmethodID jmethod = env->GetMethodID(jclazz, "invokeMethod", "(Ljava/lang/String;Ljava/lang/String;J)V");
|
||||
jmethodID jmethod = env->GetMethodID(jclazz, "invokeMethod", "(Ljava/lang/String;Ljava/lang/Object;J)V");
|
||||
jstring jstrmethod = env->NewStringUTF(method.c_str());
|
||||
jstring jstrargv = env->NewStringUTF(argv.c_str());
|
||||
|
||||
env->CallVoidMethod(channel, jmethod, jstrmethod, jstrargv, (jlong)promise);
|
||||
std::map<jobject, jobject> retMap;
|
||||
retMap[env->NewStringUTF("engine")] = jniWrapPrimity<jlong>(env, (int64_t) engine);
|
||||
retMap[env->NewStringUTF("args")] = qjs::jsToJava(env, args);
|
||||
jobject jsargs = jniWrapMap(env, retMap);
|
||||
env->CallVoidMethod(channel, jmethod, jstrmethod, jsargs, (jlong)promise);
|
||||
env->DeleteLocalRef(jstrmethod);
|
||||
env->DeleteLocalRef(jstrargv);
|
||||
jvm->DetachCurrentThread();
|
||||
env->DeleteLocalRef(jsargs);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_soko_ekibun_flutter_1qjs_JniBridge_initEngine(
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_soko_ekibun_flutter_1qjs_JniBridge_createEngine(
|
||||
JNIEnv *env,
|
||||
jobject thiz,
|
||||
jobject channel)
|
||||
@@ -75,10 +64,12 @@ Java_soko_ekibun_flutter_1qjs_JniBridge_initEngine(
|
||||
JavaVM *jvm = nullptr;
|
||||
env->GetJavaVM(&jvm);
|
||||
jobject gchannel = env->NewGlobalRef(channel);
|
||||
engine = new qjs::Engine([jvm, gchannel](std::string name, std::string args) {
|
||||
qjs::Engine *engine = new qjs::Engine([jvm, gchannel](std::string name, qjs::Value args, qjs::Engine *engine) {
|
||||
auto promise = new std::promise<qjs::JSFutureReturn>();
|
||||
jniChannelInvoke(jvm, gchannel, promise, name, args);
|
||||
return promise->get_future();
|
||||
JNIEnv *env = getEnv(jvm);
|
||||
jniChannelInvoke(env, gchannel, promise, name, args, engine);
|
||||
jvm->DetachCurrentThread();
|
||||
return promise;
|
||||
});
|
||||
return (jlong)engine;
|
||||
}
|
||||
@@ -87,6 +78,7 @@ extern "C" JNIEXPORT void JNICALL
|
||||
Java_soko_ekibun_flutter_1qjs_JniBridge_evaluate(
|
||||
JNIEnv *env,
|
||||
jobject thiz,
|
||||
jlong engine,
|
||||
jstring script,
|
||||
jstring name,
|
||||
jobject result)
|
||||
@@ -94,33 +86,86 @@ Java_soko_ekibun_flutter_1qjs_JniBridge_evaluate(
|
||||
JavaVM *jvm = nullptr;
|
||||
env->GetJavaVM(&jvm);
|
||||
jobject gresult = env->NewGlobalRef(result);
|
||||
engine->commit(qjs::EngineTask{
|
||||
env->GetStringUTFChars(script, 0),
|
||||
env->GetStringUTFChars(name, 0),
|
||||
[jvm, gresult](std::string resolve) {
|
||||
jniResultResolve(jvm, gresult, resolve);
|
||||
((qjs::Engine *)engine)->commit(qjs::EngineTask{
|
||||
[script = std::string(env->GetStringUTFChars(script, 0)),
|
||||
name = std::string(env->GetStringUTFChars(name, 0))](qjs::Context &ctx) {
|
||||
return ctx.eval(script, name.c_str(), JS_EVAL_TYPE_GLOBAL);
|
||||
},
|
||||
[jvm, gresult](std::string reject) {
|
||||
jniResultReject(jvm, gresult, reject);
|
||||
[jvm, gresult](qjs::Value resolve) {
|
||||
JNIEnv *env = getEnv(jvm);
|
||||
jniResultResolve(env, gresult, qjs::jsToJava(env, resolve));
|
||||
jvm->DetachCurrentThread();
|
||||
},
|
||||
[jvm, gresult](qjs::Value reject) {
|
||||
JNIEnv *env = getEnv(jvm);
|
||||
jniResultReject(env, gresult, qjs::getStackTrack(reject));
|
||||
jvm->DetachCurrentThread();
|
||||
}});
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_soko_ekibun_flutter_1qjs_JniBridge_close(
|
||||
JNIEnv *env,
|
||||
jobject /* this */)
|
||||
jobject thiz,
|
||||
jlong engine)
|
||||
{
|
||||
delete engine;
|
||||
delete (qjs::Engine *)engine;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_soko_ekibun_flutter_1qjs_JniBridge_call(
|
||||
JNIEnv *env,
|
||||
jobject thiz,
|
||||
jlong engine,
|
||||
jlong function,
|
||||
jobject args,
|
||||
jobject result)
|
||||
{
|
||||
JavaVM *jvm = nullptr;
|
||||
env->GetJavaVM(&jvm);
|
||||
jobject gresult = env->NewGlobalRef(result);
|
||||
jobject gargs = env->NewGlobalRef(args);
|
||||
((qjs::Engine *)engine)->commit(qjs::EngineTask{
|
||||
[jvm, function = (qjs::JSValue *)function, gargs](qjs::Context &ctx) {
|
||||
JNIEnv *env = getEnv(jvm);
|
||||
jobjectArray array = jniToArray(env, gargs);
|
||||
jsize argscount = env->GetArrayLength(array);
|
||||
qjs::JSValue *callargs = new qjs::JSValue[argscount];
|
||||
for (jsize i = 0; i < argscount; i++)
|
||||
{
|
||||
callargs[i] = qjs::javaToJs(ctx.ctx, env, env->GetObjectArrayElement(array, i));
|
||||
}
|
||||
jvm->DetachCurrentThread();
|
||||
qjs::JSValue ret = JS_Call(ctx.ctx, *function, ctx.global(), (int)argscount, callargs);
|
||||
qjs::JS_FreeValue(ctx.ctx, *function);
|
||||
if (qjs::JS_IsException(ret))
|
||||
throw qjs::exception{};
|
||||
return qjs::Value{ctx.ctx, ret};
|
||||
},
|
||||
[jvm, gresult](qjs::Value resolve) {
|
||||
JNIEnv *env = getEnv(jvm);
|
||||
jniResultResolve(env, gresult, qjs::jsToJava(env, resolve));
|
||||
jvm->DetachCurrentThread();
|
||||
},
|
||||
[jvm, gresult](qjs::Value reject) {
|
||||
JNIEnv *env = getEnv(jvm);
|
||||
jniResultReject(env, gresult, qjs::getStackTrack(reject));
|
||||
jvm->DetachCurrentThread();
|
||||
}});
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_soko_ekibun_flutter_1qjs_JniBridge_resolve(
|
||||
JNIEnv *env,
|
||||
jobject clazz,
|
||||
jlong promise, jstring data)
|
||||
jlong promise, jobject data)
|
||||
{
|
||||
((std::promise<qjs::JSFutureReturn> *)promise)->set_value((qjs::JSFutureReturn)[data = std::string(env->GetStringUTFChars(data, 0))](qjs::JSContext * ctx) {
|
||||
qjs::JSValue *ret = new qjs::JSValue{JS_NewString(ctx, data.c_str())};
|
||||
JavaVM *jvm = nullptr;
|
||||
env->GetJavaVM(&jvm);
|
||||
jobject gdata = env->NewGlobalRef(data);
|
||||
((std::promise<qjs::JSFutureReturn> *)promise)->set_value((qjs::JSFutureReturn)[jvm, gdata](qjs::JSContext * ctx) {
|
||||
JNIEnv *env = getEnv(jvm);
|
||||
qjs::JSValue *ret = new qjs::JSValue{qjs::javaToJs(ctx, env, gdata)};
|
||||
return qjs::JSOSFutureArgv{1, ret};
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user