Move all examples to a top-level directory (#1286)

* Move all examples to a top-level directory

This commit moves all API examples (Rust and C) to a top-level
`examples` directory. This is intended to make it more discoverable and
conventional as to where examples are located. Additionally all examples
are now available in both Rust and C to see how to execute the example
in the language you're familiar with. The intention is that as more
languages are supported we'd add more languages as examples here too.

Each example is also accompanied by either a `*.wat` file which is
parsed as input, or a Rust project in a `wasm` folder which is compiled
as input.

A simple driver crate was also added to `crates/misc` which executes all
the examples on CI, ensuring the C and Rust examples all execute
successfully.
This commit is contained in:
Alex Crichton
2020-03-11 15:37:24 -05:00
committed by GitHub
parent d44384da8a
commit 3c51d3adb8
33 changed files with 1131 additions and 528 deletions

118
examples/fib-debug/main.c Normal file
View File

@@ -0,0 +1,118 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <wasm.h>
#include "wasmtime.h"
#define own
int main(int argc, const char* argv[]) {
// Configuring engine to support generating of DWARF info.
// lldb can be used to attach to the program and observe
// original fib-wasm.c source code and variables.
wasm_config_t* config = wasm_config_new();
wasmtime_config_debug_info_set(config, true);
// Initialize.
printf("Initializing...\n");
wasm_engine_t* engine = wasm_engine_new_with_config(config);
wasm_store_t* store = wasm_store_new(engine);
// Load binary.
printf("Loading binary...\n");
FILE* file = fopen("target/wasm32-unknown-unknown/debug/fib.wasm", "rb");
if (!file) {
printf("> Error opening module!\n");
return 1;
}
fseek(file, 0L, SEEK_END);
size_t file_size = ftell(file);
fseek(file, 0L, SEEK_SET);
wasm_byte_vec_t binary;
wasm_byte_vec_new_uninitialized(&binary, file_size);
if (fread(binary.data, file_size, 1, file) != 1) {
printf("> Error reading module!\n");
return 1;
}
fclose(file);
// Compile.
printf("Compiling module...\n");
own wasm_module_t* module = wasm_module_new(store, &binary);
if (!module) {
printf("> Error compiling module!\n");
return 1;
}
wasm_byte_vec_delete(&binary);
// Figure out which export is the `fib` export
wasm_exporttype_vec_t module_exports;
wasm_module_exports(module, &module_exports);
int fib_idx = -1;
for (int i = 0; i < module_exports.size; i++) {
const wasm_name_t *name = wasm_exporttype_name(module_exports.data[i]);
if (name->size != 3)
continue;
if (strncmp("fib", name->data, 3) != 0)
continue;
fib_idx = i;
break;
}
wasm_exporttype_vec_delete(&module_exports);
if (fib_idx == -1) {
printf("> Error finding `fib` export!\n");
return 1;
}
// Instantiate.
printf("Instantiating module...\n");
own wasm_instance_t* instance =
wasm_instance_new(store, module, NULL, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
}
// Extract export.
printf("Extracting export...\n");
own wasm_extern_vec_t exports;
wasm_instance_exports(instance, &exports);
if (exports.size == 0) {
printf("> Error accessing exports!\n");
return 1;
}
// Getting second export (first is memory).
const wasm_func_t* run_func = wasm_extern_as_func(exports.data[fib_idx]);
if (run_func == NULL) {
printf("> Error accessing export!\n");
return 1;
}
wasm_module_delete(module);
wasm_instance_delete(instance);
// Call.
printf("Calling fib...\n");
wasm_val_t params[1] = { {.kind = WASM_I32, .of = {.i32 = 6}} };
wasm_val_t results[1];
if (wasm_func_call(run_func, params, results)) {
printf("> Error calling function!\n");
return 1;
}
wasm_extern_vec_delete(&exports);
printf("> fib(6) = %d\n", results[0].of.i32);
// Shut down.
printf("Shutting down...\n");
wasm_store_delete(store);
wasm_engine_delete(engine);
// All done.
printf("Done.\n");
return 0;
}

View File

@@ -0,0 +1,31 @@
//! Example of enabling debuginfo for wasm code which allows interactive
//! debugging of the wasm code. When using recent versions of LLDB
//! you can debug this executable and set breakpoints in wasm code and look at
//! the rust source code as input.
// To execute this example you'll need to run two commands:
//
// cargo build -p example-fib-wasm --target wasm32-unknown-unknown
// cargo run --example fib-debug
use anyhow::Result;
use wasmtime::*;
fn main() -> Result<()> {
// Load our previously compiled wasm file (built previously with Cargo) and
// also ensure that we generate debuginfo so this executable can be
// debugged in GDB.
let engine = Engine::new(Config::new().debug_info(true));
let store = Store::new(&engine);
let module = Module::from_file(&store, "target/wasm32-unknown-unknown/debug/fib.wasm")?;
let instance = Instance::new(&module, &[])?;
// Invoke `fib` export
let fib = instance
.get_export("fib")
.and_then(|e| e.func())
.ok_or(anyhow::format_err!("failed to find `fib` function export"))?
.get1::<i32, i32>()?;
println!("fib(6) = {}", fib(6)?);
Ok(())
}

View File

@@ -0,0 +1,11 @@
[package]
name = "example-fib-debug-wasm"
version = "0.1.0"
authors = ["The Wasmtime Project Developers"]
edition = "2018"
publish = false
[lib]
crate-type = ["cdylib"]
path = "fib.rs"
name = "fib"

View File

@@ -0,0 +1,11 @@
#[no_mangle]
pub extern "C" fn fib(n: u32) -> u32 {
let mut a = 1;
let mut b = 1;
for _ in 0..n {
let t = a;
a = b;
b += t;
}
return b;
}