Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception when passing a callback as parameter #59

Open
kamphaus opened this issue May 14, 2021 · 8 comments
Open

Exception when passing a callback as parameter #59

kamphaus opened this issue May 14, 2021 · 8 comments
Assignees
Labels
❓ question Further information is requested

Comments

@kamphaus
Copy link

Describe the bug

Trying to call a WASM method passing a callback parameter fails with a RuntimeException.

Steps to reproduce

The following Rust code builds the WASM code passed to Instance:

#[no_mangle]
pub extern fn greet(print: extern fn(u8)) {
    print(42)
}

The following Java code fails when trying to call the greet method:

Instance instance = new Instance(wasm);
Consumer<Object> print = (Object o) -> System.out.println("Printed: " + ((Integer) o));
instance.exports.getFunction("greet").apply(print);
instance.close();

Actual behavior

When run, this fails with the following exception:

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: java.lang.RuntimeException: Failed to convert the argument 0nth of `greet` into a WebAssembly value.
	at org.wasmer.Instance.nativeCallExportedFunction(Native Method)
	at org.wasmer.Exports.lambda$null$0(Exports.java:85)
	at org.example.wasmhost.WasmHostApplication.main(WasmHostApplication.java:45)
	... 8 more

Additional context

My Java version is:

$ java -version
openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.18.04)
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.18.04, mixed mode, sharing)
@kamphaus kamphaus added the 🐞 bug Something isn't working label May 14, 2021
@Hywan
Copy link
Contributor

Hywan commented May 17, 2021

Hello,

That's expected. Wasm understand i32, i64, f32 and f64. A callback (which is a function pointer) isn't accepted :-).

@Hywan Hywan self-assigned this May 17, 2021
@Hywan Hywan added ❓ question Further information is requested and removed 🐞 bug Something isn't working labels May 17, 2021
@kamphaus
Copy link
Author

I see that it's possible with the embedded WASM in javascript (using the wasm-bindgen rust library):
https://rustwasm.github.io/wasm-bindgen/reference/receiving-js-closures-in-rust.html

Also wasmer seems to support callbacks since wasmerio/wasmer#670 was closed in 2019.

@Hywan
Copy link
Contributor

Hywan commented May 17, 2021

wasm-bindgen is really tied to Rust and Javascript. It instruments Rust to generate specific code for Javascript. It's not the case here. wasm-bindgen is not language agnostic.

In wasmerio/wasmer#670, it's not related to passing callbacks from host to Wasm. It was related to calling Wasm functions by their index. And the index was encoded in a u32. But we were talking about Wasm functions, not host functions.

wasmer-java needs more love to support imported functions, memories etc. I'll soon get more time to work on it and to improve it largely, but supporting host functions as Wasm exported function's argument is not part of the plan, and it's very unlikely to be possible in a short-term future.

@Hywan
Copy link
Contributor

Hywan commented May 17, 2021

Note, you can store your function pointer in a Table and pass the table index to the function.
Note 2: wasmer-java doesn't support Table yet for the moment (but wasmer does support it!)

@kamphaus
Copy link
Author

Thanks, that would be great if calling back to Java code from Wasm was possible.
I also tried out GraalVM's polyglot wasm support, but no luck with that either.

@Hywan
Copy link
Contributor

Hywan commented May 17, 2021

Can you describe me what you're trying to achieve please? Maybe it's possible in another way.

@kamphaus
Copy link
Author

I'm trying to develop a plugin system for a Spring Boot Java API.
It should be possible to load/unload plugins without restarting the JVM and have well defined interfaces.
I thought it might be simpler to manage a wasm context per plugin rather than OSGi or webhooks, especially if we might use GraalVM native-image in the future.

@Hywan
Copy link
Contributor

Hywan commented May 18, 2021

Wasm is a good fit for your usecase indeed!

You can callback Java from Wasm with imported (host) function. It's not possible yet with wasmer-java but I'll add it soon :-).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
❓ question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants