GitHub - WebAssembly/wasm-c-api: Wasm C API prototype (original) (raw)
WebAssembly C and C++ API
Work in progress! No docs yet.
Design Goals
- Provide a "black box" API for embedding a Wasm engine in other C/C++ applications.
- Be completely agnostic to VM specifics.
- Non-goal: "white box" interoperability with embedder (such as combined GC instead of mere finalisation) -- much more difficult to achieve.
- Allow creation of bindings for other languages through typical C foreign function interfaces.
- Support a plain C API.
- Stick to mostly manual memory management of interface objects.
- Avoid language features that raise barrier to use.
- E.g., no exceptions or post-C++11 features in C++ API.
- E.g., no passing of structs by-value or post-C99 features in C API.
- Achieve link-time compatibility between different implementations.
- All implementation-dependent API classes are abstract and can be instantiated through factory methods only.
Interfaces
- C++ API:
- See
include/wasm.hh
for interface. - See
example/*.cc
for example usages.
- See
- C API:
- See
include/wasm.h
for interface. - See
example/*.c
for example usages.
- See
Some random explanations:
- The VM must be initialised by creating an instance of an engine (
wasm::Engine
/wasm_engine_t
) and is shut down by deleting it. Such an instance may only be created once per process. - All runtime objects are tied to a specific store (
wasm::Store
/wasm_store_t
). Multiple stores can be created, but their objects cannot interact. Every store and its objects must only be accessed in a single thread. - To exchange module objects between threads, create a shared module (
wasm::Shared<Module>
/wasm_shared_module_t
). Other objects cannot be shared in current Wasm. - Vector structures (
wasm::vec<X>
/wasm_x_vec_t
) are lightweight abstractions of a pair of a plain array and its length. The C++ API does not usestd::vector
because that does not support adopting pre-existing arrays. - References point to runtime objects, but may involve internal indirections, which may or may not be cached. Thus, pointer equality on
Ref*
or subclasses cannot be used to compare identity of the underlying objects (Ref::eq
may be added later). However,nullptr
/NULL
uniquely represents null references. - The API already encompasses current proposals like multiple return values and reference types, but not yet threads.
Prototype Implementation
- This repo contains a prototype implementation based on V8 is in
src
.- Note that this requires adding a module to V8, so it patches V8's build file.
- The C API is implemented on top of the C++ API.
- See
Makefile
for build recipe. Canonical steps to run examples:make v8-checkout
make v8
make all
Limitations
V8 implementation:
- Currently requires patching V8 by adding a module.
- Host functions (
Func::make
) create a JavaScript function internally, since V8 cannot handle raw C imports yet. - As a consequence, does not support multiple results in external calls or host functions.
- Host functions and host globals are created through auxiliary modules constructed on the fly, to work around limitations in JS API.
Shared<Module>
is currently implemented via serialisation, since V8 does not currently have direct support for cross-isolate sharing.
Other Implementations
Currently, known implementations of this API are included in
- V8 natively (both C and C++)
- Wabt (only C?)
- Wasmtime (only C?)
- Wasmer (only C, C++ coming soon)
TODO
Possible API tweaks:
- Add
Ref::eq
(or better, a subclassEqRef::eq
) for reference equality? - Add a way to return error messages from
Module::make
andModule::validate
. - Use
restrict
in C API? - Find a way to perform C callbacks through C++ without extra wrapper?
- Add iterators to
vec
class?