wasmtime_c_api/
instance.rs

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