Skip to main content

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