wasmtime_c_api/
instance.rs

1use crate::{
2    wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_store_t, wasm_trap_t, wasmtime_error_t,
3    wasmtime_extern_t, wasmtime_module_t, WasmStoreRef, WasmtimeStoreContextMut, WasmtimeStoreData,
4};
5use std::mem::MaybeUninit;
6use wasmtime::{Instance, InstancePre, Trap};
7
8#[derive(Clone)]
9pub struct wasm_instance_t {
10    store: WasmStoreRef,
11    instance: Instance,
12}
13
14wasmtime_c_api_macros::declare_ref!(wasm_instance_t);
15
16impl wasm_instance_t {
17    pub(crate) fn new(store: WasmStoreRef, instance: Instance) -> wasm_instance_t {
18        wasm_instance_t { store, instance }
19    }
20}
21
22#[unsafe(no_mangle)]
23pub unsafe extern "C" fn wasm_instance_new(
24    store: &mut wasm_store_t,
25    wasm_module: &wasm_module_t,
26    imports: *const wasm_extern_vec_t,
27    result: Option<&mut *mut wasm_trap_t>,
28) -> Option<Box<wasm_instance_t>> {
29    let imports = (*imports)
30        .as_slice()
31        .iter()
32        .filter_map(|import| match import {
33            Some(i) => Some(i.which.clone()),
34            None => None,
35        })
36        .collect::<Vec<_>>();
37    match Instance::new(store.store.context_mut(), &wasm_module.module, &imports) {
38        Ok(instance) => Some(Box::new(wasm_instance_t::new(
39            store.store.clone(),
40            instance,
41        ))),
42        Err(e) => {
43            if let Some(ptr) = result {
44                *ptr = Box::into_raw(Box::new(wasm_trap_t::new(e)));
45            }
46            None
47        }
48    }
49}
50
51#[unsafe(no_mangle)]
52pub unsafe extern "C" fn wasm_instance_exports(
53    instance: &mut wasm_instance_t,
54    out: &mut wasm_extern_vec_t,
55) {
56    let store = instance.store.clone();
57    out.set_buffer(
58        instance
59            .instance
60            .exports(instance.store.context_mut())
61            .map(|e| {
62                Some(Box::new(wasm_extern_t {
63                    which: e.into_extern(),
64                    store: store.clone(),
65                }))
66            })
67            .collect(),
68    );
69}
70
71#[unsafe(no_mangle)]
72pub unsafe extern "C" fn wasmtime_instance_new(
73    store: WasmtimeStoreContextMut<'_>,
74    module: &wasmtime_module_t,
75    imports: *const wasmtime_extern_t,
76    nimports: usize,
77    instance: &mut Instance,
78    trap_ptr: &mut *mut wasm_trap_t,
79) -> Option<Box<wasmtime_error_t>> {
80    let imports = crate::slice_from_raw_parts(imports, nimports)
81        .iter()
82        .map(|i| i.to_extern())
83        .collect::<Vec<_>>();
84    handle_instantiate(
85        Instance::new(store, &module.module, &imports),
86        instance,
87        trap_ptr,
88    )
89}
90
91pub(crate) fn handle_instantiate(
92    instance: anyhow::Result<Instance>,
93    instance_ptr: &mut Instance,
94    trap_ptr: &mut *mut wasm_trap_t,
95) -> Option<Box<wasmtime_error_t>> {
96    match instance {
97        Ok(i) => {
98            *instance_ptr = i;
99            None
100        }
101        Err(e) => {
102            if e.is::<Trap>() {
103                *trap_ptr = Box::into_raw(Box::new(wasm_trap_t::new(e)));
104                None
105            } else {
106                Some(Box::new(e.into()))
107            }
108        }
109    }
110}
111
112#[unsafe(no_mangle)]
113pub unsafe extern "C" fn wasmtime_instance_export_get(
114    store: WasmtimeStoreContextMut<'_>,
115    instance: &Instance,
116    name: *const u8,
117    name_len: usize,
118    item: &mut MaybeUninit<wasmtime_extern_t>,
119) -> bool {
120    let name = crate::slice_from_raw_parts(name, name_len);
121    let name = match std::str::from_utf8(name) {
122        Ok(name) => name,
123        Err(_) => return false,
124    };
125    match instance.get_export(store, name) {
126        Some(e) => {
127            crate::initialize(item, e.into());
128            true
129        }
130        None => false,
131    }
132}
133
134#[unsafe(no_mangle)]
135pub unsafe extern "C" fn wasmtime_instance_export_nth(
136    store: WasmtimeStoreContextMut<'_>,
137    instance: &Instance,
138    index: usize,
139    name_ptr: &mut *const u8,
140    name_len: &mut usize,
141    item: &mut MaybeUninit<wasmtime_extern_t>,
142) -> bool {
143    match instance.exports(store).nth(index) {
144        Some(e) => {
145            *name_ptr = e.name().as_ptr();
146            *name_len = e.name().len();
147            crate::initialize(item, e.into_extern().into());
148            true
149        }
150        None => false,
151    }
152}
153
154#[repr(transparent)]
155pub struct wasmtime_instance_pre_t {
156    pub(crate) underlying: InstancePre<WasmtimeStoreData>,
157}
158
159#[unsafe(no_mangle)]
160pub unsafe extern "C" fn wasmtime_instance_pre_delete(_instance_pre: Box<wasmtime_instance_pre_t>) {
161}
162
163#[unsafe(no_mangle)]
164pub unsafe extern "C" fn wasmtime_instance_pre_instantiate(
165    instance_pre: &wasmtime_instance_pre_t,
166    store: WasmtimeStoreContextMut<'_>,
167    instance_ptr: &mut Instance,
168    trap_ptr: &mut *mut wasm_trap_t,
169) -> Option<Box<wasmtime_error_t>> {
170    let result = instance_pre.underlying.instantiate(store);
171    handle_instantiate(result, instance_ptr, trap_ptr)
172}
173
174#[unsafe(no_mangle)]
175pub unsafe extern "C" fn wasmtime_instance_pre_module(
176    instance_pre: &wasmtime_instance_pre_t,
177) -> Box<wasmtime_module_t> {
178    let module = instance_pre.underlying.module().clone();
179    Box::new(wasmtime_module_t { module })
180}