When a module is instantiated, it is possible to import functions or values from Scala into the module. For instance, let’s assume we defined a function that prints its parameter on the console, and a simple WebAssembly module that imports and calls it.
import swam.text._
import swam.runtime._
import cats.effect._
import java.nio.file.Paths
implicit val cs = IO.contextShift(scala.concurrent.ExecutionContext.global)
def log(i: Int) = IO(println(s"got $i"))
val f =
Blocker[IO].use { blocker =>
for {
engine <- Engine[IO](blocker)
tcompiler <- Compiler[IO](blocker)
mod <- engine.compile(tcompiler.stream(Paths.get("logged.wat"), true, blocker))
inst <- mod.importing("console", "log" -> log _).instantiate
f <- inst.exports.typed.function[Int, Int]("add42")
} yield f
}.unsafeRunSync()
running function f
logs the parameter.
f(4).unsafeRunSync()
// got 4
// res0: Int = 46
It is also possible to use HList
s to represent imported modules with several exposed fields. For instance, let’s import the console
module with an extra colors
field exposed.
import shapeless._
Blocker[IO].use { blocker =>
for {
engine <- Engine[IO](blocker)
tcompiler <- Compiler[IO](blocker)
mod <- engine.compile(tcompiler.stream(Paths.get("logged.wat"), true, blocker))
inst <- mod.importing("console", "log" -> log _ :: "colors" -> 256 :: HNil).instantiate
f <- inst.exports.typed.function[Int, Int]("add42")
} yield f
}