Importing a function from JS (original) (raw)
- Introduction
- 1. Examples
- 1.1. Hello, World!
- 1.2. Using console.log
- 1.3. Small Wasm files
- 1.4. Without a Bundler
- 1.5. Synchronous Instantiation
- 1.6. Importing functions from JS
- 1.7. Working with char
- 1.8. js-sys: WebAssembly in WebAssembly
- 1.9. web-sys: DOM hello world
- 1.10. web-sys: Closures
- 1.11. web-sys: performance.now
- 1.12. web-sys: using fetch
- 1.13. web-sys: Weather report
- 1.14. web-sys: canvas hello world
- 1.15. web-sys: canvas Julia set
- 1.16. web-sys: WebAudio
- 1.17. web-sys: WebGL
- 1.18. web-sys: WebSockets
- 1.19. web-sys: WebRTC DataChannel
- 1.20. web-sys: requestAnimationFrame
- 1.21. web-sys: A Simple Paint Program
- 1.22. web-sys: Wasm in Web Worker
- 1.23. Parallel Raytracing
- 1.24. Wasm Audio Worklet
- 1.25. web-sys: A TODO MVC App
- 2. Reference
- 2.1. Deployment
- 2.2. JS snippets
- 2.3. Static JS Objects
- 2.4. Passing Rust Closures to JS
- 2.5. Receiving JS Closures in Rust
- 2.6. Promises and Futures
- 2.7. Iterating over JS Values
- 2.8. Arbitrary Data with Serde
- 2.9. Accessing Properties of Untyped JS Values
- 2.10. Working with Duck-Typed Interfaces
- 2.11. Command Line Interface
- 2.12. Optimizing for Size
- 2.13. Supported Rust Targets
- 2.14. Supported Browsers
- 2.15. Support for Weak References
- 2.16. Support for Reference Types
- 2.17. Supported Types
- 2.18. #[wasm_bindgen] Attributes
- 2.18.1. On JavaScript Imports
- 2.18.1.1. catch
- 2.18.1.2. constructor
- 2.18.1.3. extends
- 2.18.1.4. getter and setter
- 2.18.1.5. final
- 2.18.1.6. indexing_getter, indexing_setter, and indexing_deleter
- 2.18.1.7. js_class = "Blah"
- 2.18.1.8. js_name
- 2.18.1.9. js_namespace
- 2.18.1.10. method
- 2.18.1.11. module = "blah"
- 2.18.1.12. raw_module = "blah"
- 2.18.1.13. no_deref
- 2.18.1.14. static_method_of = Blah
- 2.18.1.15. structural
- 2.18.1.16. typescript_type
- 2.18.1.17. variadic
- 2.18.1.18. vendor_prefix
- 2.18.1.1. catch
- 2.18.2. On Rust Exports
- 2.18.2.1. constructor
- 2.18.2.2. js_name = Blah
- 2.18.2.3. js_class = Blah
- 2.18.2.4. readonly
- 2.18.2.5. skip
- 2.18.2.6. skip_jsdoc
- 2.18.2.7. start
- 2.18.2.8. main
- 2.18.2.9. typescript_custom_section
- 2.18.2.10. getter and setter
- 2.18.2.11. inspectable
- 2.18.2.12. skip_typescript
- 2.18.2.13. getter_with_clone
- 2.18.2.14. unchecked_return_type and unchecked_param_type
- 2.18.2.15. return_description and param_description
- 2.18.2.1. constructor
- 3. web-sys
- 4. Testing with wasm-bindgen-test
- 5. Contributing to wasm-bindgen
- 5.2. Internal Design
- 5.3. js-sys
- 5.4. web-sys
- 5.5. Publishing
- 5.6. Team
The `wasm-bindgen` Guide
Now that we've exported some rich functionality to JS it's also time to import some! The goal here is to basically implement JS import
statements in Rust, with fancy types and all.
First up, let's say we invert the function above and instead want to generate greetings in JS but call it from Rust. We might have, for example:
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(module = "./greet")]
extern "C" {
fn greet(a: &str) -> String;
}
fn other_code() {
let greeting = greet("foo");
// ...
}
#}
The basic idea of imports is the same as exports in that we'll have shims in both JS and Rust doing the necessary translation. Let's first see the JS shim in action:
import * as wasm from './foo_bg';
import { greet } from './greet';
// ...
export function __wbg_f_greet(ptr0, len0, wasmretptr) {
const [retptr, retlen] = passStringToWasm(greet(getStringFromWasm(ptr0, len0)));
(new Uint32Array(wasm.memory.buffer))[wasmretptr / 4] = retlen;
return retptr;
}
The getStringFromWasm
and passStringToWasm
are the same as we saw before, and like with __wbindgen_object_drop_ref
far above we've got this weird export from our module now! The __wbg_f_greet
function is what's generated bywasm-bindgen
to actually get imported in the foo.wasm
module.
The generated foo.js
we see imports from the ./greet
module with the greet
name (was the function import in Rust said) and then the __wbg_f_greet
function is shimming that import.
There's some tricky ABI business going on here so let's take a look at the generated Rust as well. Like before this is simplified from what's actually generated.
# #![allow(unused_variables)]
#fn main() {
extern "C" fn greet(a: &str) -> String {
extern "C" {
fn __wbg_f_greet(a_ptr: *const u8, a_len: usize, ret_len: *mut usize) -> *mut u8;
}
unsafe {
let a_ptr = a.as_ptr();
let a_len = a.len();
let mut __ret_strlen = 0;
let mut __ret_strlen_ptr = &mut __ret_strlen as *mut usize;
let _ret = __wbg_f_greet(a_ptr, a_len, __ret_strlen_ptr);
String::from_utf8_unchecked(
Vec::from_raw_parts(_ret, __ret_strlen, __ret_strlen)
)
}
}
#}
Here we can see that the greet
function was generated but it's largely just a shim around the __wbg_f_greet
function that we're calling. The ptr/len pair for the argument is passed as two arguments and for the return value we're receiving one value (the length) indirectly while directly receiving the returned pointer.