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