1

I am learning how to target WASM with Rust through this tutorial. I want to be able to separate my domain code from the code that exposes it to WASM. That way, I could re-use the domain code in a non-WASM application with no fuss. I can't find any examples that do this, and I don't know that it's supported.

Right now, what I'm doing is wrapping my vanilla Rust struct with another struct that has wrappers around the domain class's public methods. I'm almost sure this is not the proper way to do it, but it works for now.

I want to be able to bind CellValue to WASM.

// Inside a vanilla Rust library

// We could bind CellValue with #[wasm_bindgen],
// but I want to keep all WASM stuff out of this library
enum CellValue {
    Live = 0,
    Dead = 1
}

// ...

struct World {
    // ...
    cells: Vec<CellValue> // need to bind a direct reference to the values in here
}

This is how I am exposing World to WASM - I'm wrapping it in GOL and implementing methods in GOL so that the WASM can interact with World.

// Inside the wasm binding library

#[wasm_bindgen]
pub struct GOL {
    world: gol::World
}


#[wasm_bindgen]
impl GOL {
    pub fn make_new(rows: usize, cols: usize) -> Self
    {
        Self {
            world: GameOfLife::make_new(rows, cols)
        }
    }

    // and so on...
}

For CellValue, I can't mimic the approach I took with GOL because I need to be able to reference the data inside each cell that's held by World.

Like I said, the whole reason I'm jumping through these hoops is so that I can avoid peppering my domain code with #[wasm_bindgen]. Is it even possible to get this kind of binding?

  • It looks like your question might be answered by the answers of [How do I apply a macro attribute to a function defined in a separate module?](https://stackoverflow.com/q/53364002/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Jun 20 '19 at 02:30

1 Answers1

0

Update: I found a workable solution by looking at this library. It's a ZX Spectrum emulator written in this fashion, with wasm_bindgen sequestered off in an interface. The paradigm is to interop via an unsafe pointer like so:

#[wasm_bindgen]
pub fn get_cell_value(world: *mut World) -> *const CellValue // return a raw reference to the type defined in the domain
{
    // Return a reference to the first element in the array
}

Then, on the JavaScript side, do something like this:

import { memory } from "gol/gol_bg"; // Actual WASM generated by wasm_bindgen
import { make_world, get_cell_array } from "wasm-game-of-life";

// ...

const world = make_world(width, height);

const cellsPtr = get_cells_array(world); // Pointer to the first element of the Vec

const cells = new Uint8Array(memory.buffer, cellsPtr, width * height);