1# Importing a function from JS 2 3Now that we've exported some rich functionality to JS it's also time to import 4some! The goal here is to basically implement JS `import` statements in Rust, 5with fancy types and all. 6 7First up, let's say we invert the function above and instead want to generate 8greetings in JS but call it from Rust. We might have, for example: 9 10```rust 11#[wasm_bindgen(module = "./greet")] 12extern "C" { 13 fn greet(a: &str) -> String; 14} 15 16fn other_code() { 17 let greeting = greet("foo"); 18 // ... 19} 20``` 21 22The basic idea of imports is the same as exports in that we'll have shims in 23both JS and Rust doing the necessary translation. Let's first see the JS shim in 24action: 25 26```js 27import * as wasm from './foo_bg'; 28 29import { greet } from './greet'; 30 31// ... 32 33export function __wbg_f_greet(ptr0, len0, wasmretptr) { 34 const [retptr, retlen] = passStringToWasm(greet(getStringFromWasm(ptr0, len0))); 35 (new Uint32Array(wasm.memory.buffer))[wasmretptr / 4] = retlen; 36 return retptr; 37} 38``` 39 40The `getStringFromWasm` and `passStringToWasm` are the same as we saw before, 41and like with `__wbindgen_object_drop_ref` far above we've got this weird export 42from our module now! The `__wbg_f_greet` function is what's generated by 43`wasm-bindgen` to actually get imported in the `foo.wasm` module. 44 45The generated `foo.js` we see imports from the `./greet` module with the `greet` 46name (was the function import in Rust said) and then the `__wbg_f_greet` 47function is shimming that import. 48 49There's some tricky ABI business going on here so let's take a look at the 50generated Rust as well. Like before this is simplified from what's actually 51generated. 52 53```rust 54extern "C" fn greet(a: &str) -> String { 55 extern "C" { 56 fn __wbg_f_greet(a_ptr: *const u8, a_len: usize, ret_len: *mut usize) -> *mut u8; 57 } 58 unsafe { 59 let a_ptr = a.as_ptr(); 60 let a_len = a.len(); 61 let mut __ret_strlen = 0; 62 let mut __ret_strlen_ptr = &mut __ret_strlen as *mut usize; 63 let _ret = __wbg_f_greet(a_ptr, a_len, __ret_strlen_ptr); 64 String::from_utf8_unchecked( 65 Vec::from_raw_parts(_ret, __ret_strlen, __ret_strlen) 66 ) 67 } 68} 69``` 70 71Here we can see that the `greet` function was generated but it's largely just a 72shim around the `__wbg_f_greet` function that we're calling. The ptr/len pair 73for the argument is passed as two arguments and for the return value we're 74receiving one value (the length) indirectly while directly receiving the 75returned pointer. 76