Open IKhomZera opened 1 year ago
If you don't want to use WebAssembly and prefer to directly run JavaScript with C++, then this library is not suitable. But if you want to run WebAssembly through C++, and execute some JavaScript inside WebAssembly, then this library is somewhat suitable.
@L-jasmine I want to run WebAssembly through C++, and execute some JavaScript inside WebAssembly.
I see here https://github.com/second-state/wasmedge-quickjs/blob/main/examples/embed_js/src/main.rs how to use it through Rust app.
What I want to understand is re how to use this lib through C++
You can use the Wasmedge CPP API to run Wasmedge inside your C++ program, and then use Wasmedge to load the WebAssembly from the 'release' page. Your C++ program will not directly use this library.
@L-jasmine Here is what I'm trying currently to do:
#include <iostream>
#include <wasmedge/wasmedge.h>
#include <stdio.h>
#include <string>
#include <sstream>
using namespace std;
int runJS() {
/* Create the configure context and add the WASI support. */
/* This step is not necessary unless you need WASI support. */
WasmEdge_ConfigureContext *ConfCxt = WasmEdge_ConfigureCreate();
WasmEdge_ConfigureAddHostRegistration(ConfCxt,
WasmEdge_HostRegistration_Wasi);
/* The configure and store context to the VM creation can be NULL. */
WasmEdge_VMContext *VMCxt = WasmEdge_VMCreate(ConfCxt, NULL);
// /* The parameters and returns arrays. */
WasmEdge_Value Params[2] = {WasmEdge_ValueGenI32(5), WasmEdge_ValueGenI32(5)};
WasmEdge_Value Returns[1];
// /* Function name. */
WasmEdge_String FuncName = WasmEdge_StringCreateByCString("main");
/* Result. */
WasmEdge_Result Res;
/* Step 1: Load WASM file. */
Res = WasmEdge_VMLoadWasmFromFile(VMCxt, "wasmedge_quickjs.wasm");
/*
* Developers can load the WASM binary from buffer with the
* `WasmEdge_VMLoadWasmFromBuffer()` API, or from
* `WasmEdge_ASTModuleContext` object with the
* `WasmEdge_VMLoadWasmFromASTModule()` API.
*/
if (!WasmEdge_ResultOK(Res)) {
printf("Loading phase failed: %s\n", WasmEdge_ResultGetMessage(Res));
return 1;
}
/* Step 2: Validate the WASM module. */
Res = WasmEdge_VMValidate(VMCxt);
if (!WasmEdge_ResultOK(Res)) {
printf("Validation phase failed: %s\n", WasmEdge_ResultGetMessage(Res));
return 1;
}
/* Step 3: Instantiate the WASM module. */
Res = WasmEdge_VMInstantiate(VMCxt);
/*
* Developers can load, validate, and instantiate another WASM module to
* replace the instantiated one. In this case, the old module will be
* cleared, but the registered modules are still kept.
*/
if (!WasmEdge_ResultOK(Res)) {
printf("Instantiation phase failed: %s\n",
WasmEdge_ResultGetMessage(Res));
return 1;
}
/*
* Step 4: Execute WASM functions. You can execute functions repeatedly
* after instantiation.
*/
Res = WasmEdge_VMExecute(VMCxt, FuncName, Params, 2, Returns, 1);
if (WasmEdge_ResultOK(Res)) {
printf("Get the result: %d\n", WasmEdge_ValueGetI32(Returns[0]));
} else {
printf("Execution phase failed: %s\n", WasmEdge_ResultGetMessage(Res));
}
/* Resources deallocations. */
WasmEdge_VMDelete(VMCxt);
WasmEdge_ConfigureDelete(ConfCxt);
WasmEdge_StringDelete(FuncName);
return 0;
}
int main(int argc, char **argv) {
runJS();
return 0;
}
I load wasmedge-quickjs wasm file wasmedge_quickjs.wasm
and then trying to run there a main
function.
Then run it this way:
gcc main.cpp -lwasmedge && ./a.out
and it prints some result Get the result: 39894674
My current issue is the following:
main
function accepts 2 parameters of I32, but I want to pass there a JS file name and args, simialar to CLI example $ wasmedge --dir .:. wasmedge_quickjs.wasm example_js/hello.js WasmEdge Runtime
Could you help me with this?
The arguments for the main function in WebAssembly are obtained from WASI, so you need to set the arguments you want to pass to the main function in the WASI module, just like what was done in the link provided above.
Another point is that, for WebAssembly supporting WASI, their startup function is often _start
instead of main
. This is a function with no parameters and no return.
So your RunJs() should be modified to
int runJS() {
/* Create the configure context and add the WASI support. */
/* This step is not necessary unless you need WASI support. */
WasmEdge_ConfigureContext *ConfCxt = WasmEdge_ConfigureCreate();
WasmEdge_ConfigureAddHostRegistration(ConfCxt,
WasmEdge_HostRegistration_Wasi);
/* The configure and store context to the VM creation can be NULL. */
WasmEdge_VMContext *VMCxt = WasmEdge_VMCreate(ConfCxt, NULL);
// /* The parameters and returns arrays. */
WasmEdge_Value Params[0] = {}; //maybe, I am not very familiar with C++ syntax.
WasmEdge_Value Returns[0] = {}; //maybe, I am not very familiar with C++ syntax.
// /* Function name. */
WasmEdge_String FuncName = WasmEdge_StringCreateByCString("_start");
/* Result. */
WasmEdge_Result Res;
.....
@L-jasmine that does work quite well, thanks a lot for your support 🥇
Just one final thing
My js file looks like the following:
import * as os from 'os';
import * as std from 'std';
import * as process from 'process'
args = args.slice(1);
print('echo Hello: ', ...args);
Is there a way to get this output after calling WasmEdge_VMExecute
and store into C++ variable?
Sorry for the delayed response. To solve this issue, you need to make changes in the Rust part. You can either fork this repository or create a new one that references this Rust library. In this way, Rust (Wasm) can retain the execution result from JavaScript, and then you can retrieve the saved result from Rust (Wasm) in C++ using Wasmedge.
Similar to https://github.com/second-state/wasmedge-quickjs/blob/main/examples/embed_js/src/main.rs
Can I use this lib to embed JS code into C++ app?