Closed bangonkali closed 4 years ago
Hi @bangonkali
You should be able to use WASM on Android. I just verified that it works on latest version of LiquidCore (HEAD). I am not sure about the last release (0.6.2). I haven't checked, but you can try it.
See https://developer.mozilla.org/en-US/docs/WebAssembly
The WebAssembly
API object exists and should be accessible (below untested). I have no practical experience with WASM, so you will have to experiment.
JSObject webAssembly = context.property("WebAssembly").toObject();
You can then get its methods and call them, e.g.:
byte sourceCode[] = ... // wherever your compiled code came from
JSFunction compile = webAssembly.property("compile").toFunction();
JSUint8Array byteArray = new JSUint8Array(context, sourceCode.length);
System.arraycopy(sourceCode, 0, byteArray, 0, byteArray.length);
JSArrayBuffer buffer = byteArray.buffer();
JSObject promise = compile.call(compile, buffer).toObject();
// etc ...
I will post my report here after I am able to test with the latest stable release.
Since I'm very new with the Microservice - (ie, had to ask for some advice previously). Please bear with me with this approach.
main.c
#define WASM_EXPORT __attribute__((visibility("default")))
WASM_EXPORT
int main() {
return 42;
}
index.js
setInterval(function() {}, 1000)
LiquidCore.on( 'req_init', function(wasmBase64) {
try {
var byteArray = Buffer.from(wasmBase64, 'base64');
WebAssembly.instantiate(byteArray).then(results => {
instance = results.instance;
var outcome = instance.exports.main();
LiquidCore.emit( 'res_init', { message: `Response: ${outcome}` } );
}).catch((err) => {
LiquidCore.emit( 'log', { message: `Error: ${err}` } );
});
} catch (ex) {
LiquidCore.emit( 'log', { message: `Error: ${ex}` } );
}
})
LiquidCore.on( 'req_ping', function() {
LiquidCore.emit( 'res_pong', { message: `End of lifecycle!` } );
process.exit(0);
})
LiquidCore.emit( 'res_ready' )
Currently, I did not have the stack to compile C programs to WASM, so I utilized this site and downloaded the compiled code.
Based on the doc from here, I wrote the following Test Code for the Kotlin Android side:
val res = URI("android.resource://package.name/raw/index")
val wasmStream: InputStream = resources.openRawResource(R.raw.main)
val wasmBytes: ByteArray = wasmStream.readBytes()
val wasmBase64 = Base64.encodeToString(
wasmBytes,
Base64.DEFAULT or Base64.NO_WRAP
)
Log.d(TAG, "Wasm Loaded (Base 64): $wasmBase64")
val logListener =
EventListener { service, event, payload ->
Log.d(TAG, "Event:$event ${payload.getString("message")}")
}
val readyListener =
EventListener { service, event, payload ->
Log.d(TAG, "Event:$event")
service.emit("req_init", wasmBase64)
}
val initListener =
EventListener { service, event, payload ->
Log.d(TAG, "Event:$event ${payload.getString("message")}")
service.emit("req_ping")
}
val pongListener =
EventListener { service, event, payload ->
Log.d(TAG, "Event:$event ${payload.getString("message")}")
}
val startListener =
ServiceStartListener { service ->
Log.d(TAG, "Microservice started.")
service.addEventListener("log", logListener)
service.addEventListener("res_ready", readyListener)
service.addEventListener("res_init", initListener)
service.addEventListener("res_pong", pongListener)
}
service = MicroService(
activity,
res,
startListener
)
service.start()
Following were attached as res/raw
:
Thankfully, I had the following results:
2019-11-25 23:54:05.889 18604-18604/se.netzon.blocks D/DashboardFragment: Wasm Loaded (Base 64): AGFzbQEAAAABCAJgAABgAAF/AwQDAAEABAUBcAEBAQUDAQACBg8CfwFBgIgEC38AQYCIBAsHKAQGbWVtb3J5AgAGX3N0YXJ0AAAEbWFpbgABC19faGVhcF9iYXNlAwEKDAMCAAsEAEEqCwIACwALB2xpbmtpbmcDAQAAKQRuYW1lASIDAAZfc3RhcnQBBG1haW4CEV9fd2FzbV9jYWxsX2N0b3Jz
2019-11-25 23:54:06.217 18604-18685/se.netzon.blocks D/DashboardFragment: Microservice started.
2019-11-25 23:54:06.245 18604-18685/se.netzon.blocks D/DashboardFragment: Event:res_ready
2019-11-25 23:54:06.253 18604-18685/se.netzon.blocks D/DashboardFragment: Event:res_init Response: 42
2019-11-25 23:54:06.254 18604-18685/se.netzon.blocks D/DashboardFragment: Event:res_pong End of lifecycle!
With emphasis on:
Event:res_init Response: 42
Conclusion: WASM works on 'com.github.LiquidPlayer:LiquidCore:0.6.2'
Side note: I have been reading about WASI which is somewhat similar but focusing on the runtime only. Maybe in the future we can let go of Node altogether and just use WASI. But for now, this will do for my experiment.
Do you have any advice on how to get the context
of a Microservice
so that I can do like you did in your example above?
JSObject webAssembly = context.property("WebAssembly").toObject();
I will close this for now as I am able to achieve my primary objective with your guidance. Any advice will help very much though. Thanks!
Glad that it works! I am really interested in using WASM with LiquidCore, but I haven't had the opportunity to play with it. The bad news is that it won't work on iOS, at least not yet. JavaScriptCore does not seem to support it.
The simplest way to get the JSContext
is to get it from the payload
object in one of your listeners with payload.getContext()
.
It's not the cleanest solution. I hid the context intentionally for historical reasons, but those reasons are probably not that useful anymore. Ideally you would get the context from the Process
object with service.getProcess().getContext()
. But it would have to be added to the API.
The bad news is that it won't work on iOS, at least not yet.
Hopefully, they will support WASM soon. I believe Webkit already supports WASM.
The simplest way to get the
JSContext
is to get it from thepayload
object in one of your listeners withpayload.getContext()
.
I will do this for now while I'll wait for service.getProcess().getContext()
. Thanks!
it's now supported in javascriptcore as of feb 2020
This is not a bug but rather a request for guidance on how to get started with running WASM/WASI on V8 embedded in LiquidCore. I think the V8 version supports WASM. Any leads will do. I, of course, will put my investigation notes here also.
A short overview of the use case. There is a library of scripts that anyone can contribute to. We want to optimize these scripts by requiring them to be written in RUST/C++ -> WASM. They can be loaded in runtime from the cloud to be executed in the Phone at any time.