wasmtime_c_api/component/
linker.rs

1use crate::{
2    WasmtimeStoreContextMut, WasmtimeStoreData, wasm_engine_t, wasmtime_component_resource_type_t,
3    wasmtime_error_t, wasmtime_module_t,
4};
5use std::ffi::c_void;
6use wasmtime::component::{Instance, Linker, LinkerInstance, Val};
7
8use super::{wasmtime_component_t, wasmtime_component_val_t};
9
10#[repr(transparent)]
11pub struct wasmtime_component_linker_t {
12    pub(crate) linker: Linker<WasmtimeStoreData>,
13}
14
15#[repr(transparent)]
16pub struct wasmtime_component_linker_instance_t<'a> {
17    pub(crate) linker_instance: LinkerInstance<'a, WasmtimeStoreData>,
18}
19
20#[unsafe(no_mangle)]
21pub extern "C" fn wasmtime_component_linker_new(
22    engine: &wasm_engine_t,
23) -> Box<wasmtime_component_linker_t> {
24    Box::new(wasmtime_component_linker_t {
25        linker: Linker::new(&engine.engine),
26    })
27}
28
29#[unsafe(no_mangle)]
30pub extern "C" fn wasmtime_component_linker_allow_shadowing(
31    linker: &mut wasmtime_component_linker_t,
32    allow: bool,
33) {
34    linker.linker.allow_shadowing(allow);
35}
36
37#[unsafe(no_mangle)]
38pub extern "C" fn wasmtime_component_linker_root(
39    linker: &mut wasmtime_component_linker_t,
40) -> Box<wasmtime_component_linker_instance_t<'_>> {
41    Box::new(wasmtime_component_linker_instance_t {
42        linker_instance: linker.linker.root(),
43    })
44}
45
46#[unsafe(no_mangle)]
47pub extern "C" fn wasmtime_component_linker_instantiate(
48    linker: &wasmtime_component_linker_t,
49    context: WasmtimeStoreContextMut<'_>,
50    component: &wasmtime_component_t,
51    instance_out: &mut Instance,
52) -> Option<Box<wasmtime_error_t>> {
53    let result = linker.linker.instantiate(context, &component.component);
54    crate::handle_result(result, |instance| *instance_out = instance)
55}
56
57#[unsafe(no_mangle)]
58pub extern "C" fn wasmtime_component_linker_delete(_linker: Box<wasmtime_component_linker_t>) {}
59
60#[unsafe(no_mangle)]
61pub unsafe extern "C" fn wasmtime_component_linker_instance_add_instance<'a>(
62    linker_instance: &'a mut wasmtime_component_linker_instance_t<'a>,
63    name: *const u8,
64    name_len: usize,
65    linker_instance_out: &mut *mut wasmtime_component_linker_instance_t<'a>,
66) -> Option<Box<wasmtime_error_t>> {
67    let name = unsafe { std::slice::from_raw_parts(name, name_len) };
68    let Ok(name) = std::str::from_utf8(name) else {
69        return crate::bad_utf8();
70    };
71
72    let result = linker_instance.linker_instance.instance(&name);
73    crate::handle_result(result, |linker_instance| {
74        *linker_instance_out = Box::into_raw(Box::new(wasmtime_component_linker_instance_t {
75            linker_instance,
76        }));
77    })
78}
79
80#[unsafe(no_mangle)]
81pub unsafe extern "C" fn wasmtime_component_linker_instance_add_module(
82    linker_instance: &mut wasmtime_component_linker_instance_t,
83    name: *const u8,
84    name_len: usize,
85    module: &wasmtime_module_t,
86) -> Option<Box<wasmtime_error_t>> {
87    let name = unsafe { std::slice::from_raw_parts(name, name_len) };
88    let Ok(name) = std::str::from_utf8(name) else {
89        return crate::bad_utf8();
90    };
91
92    let result = linker_instance
93        .linker_instance
94        .module(&name, &module.module);
95
96    crate::handle_result(result, |_| ())
97}
98
99pub type wasmtime_component_func_callback_t = extern "C" fn(
100    *mut c_void,
101    WasmtimeStoreContextMut<'_>,
102    *const wasmtime_component_val_t,
103    usize,
104    *mut wasmtime_component_val_t,
105    usize,
106) -> Option<Box<wasmtime_error_t>>;
107
108#[unsafe(no_mangle)]
109pub unsafe extern "C" fn wasmtime_component_linker_instance_add_func(
110    linker_instance: &mut wasmtime_component_linker_instance_t,
111    name: *const u8,
112    name_len: usize,
113    callback: wasmtime_component_func_callback_t,
114    data: *mut c_void,
115    finalizer: Option<extern "C" fn(*mut c_void)>,
116) -> Option<Box<wasmtime_error_t>> {
117    let name = unsafe { std::slice::from_raw_parts(name, name_len) };
118    let Ok(name) = std::str::from_utf8(name) else {
119        return crate::bad_utf8();
120    };
121
122    let foreign = crate::ForeignData { data, finalizer };
123
124    let result = linker_instance
125        .linker_instance
126        .func_new(&name, move |ctx, _ty, args, rets| {
127            let _ = &foreign;
128
129            let args = args
130                .iter()
131                .map(|x| wasmtime_component_val_t::from(x))
132                .collect::<Vec<_>>();
133
134            let mut c_rets = vec![wasmtime_component_val_t::Bool(false); rets.len()];
135
136            let res = callback(
137                foreign.data,
138                ctx,
139                args.as_ptr(),
140                args.len(),
141                c_rets.as_mut_ptr(),
142                c_rets.len(),
143            );
144
145            if let Some(res) = res {
146                return Err((*res).into());
147            }
148
149            for (rust_val, c_val) in std::iter::zip(rets, c_rets) {
150                *rust_val = Val::from(&c_val);
151            }
152
153            Ok(())
154        });
155
156    crate::handle_result(result, |_| ())
157}
158
159#[unsafe(no_mangle)]
160#[cfg(feature = "wasi")]
161pub unsafe extern "C" fn wasmtime_component_linker_add_wasip2(
162    linker: &mut wasmtime_component_linker_t,
163) -> Option<Box<wasmtime_error_t>> {
164    let result = wasmtime_wasi::p2::add_to_linker_sync(&mut linker.linker);
165    crate::handle_result(result, |_| ())
166}
167
168#[unsafe(no_mangle)]
169pub unsafe extern "C" fn wasmtime_component_linker_define_unknown_imports_as_traps(
170    linker: &mut wasmtime_component_linker_t,
171    component: &wasmtime_component_t,
172) -> Option<Box<wasmtime_error_t>> {
173    let result = linker
174        .linker
175        .define_unknown_imports_as_traps(&component.component);
176    crate::handle_result(result, |_| ())
177}
178
179pub type wasmtime_component_resource_destructor_t =
180    extern "C" fn(*mut c_void, WasmtimeStoreContextMut<'_>, u32) -> Option<Box<wasmtime_error_t>>;
181
182#[unsafe(no_mangle)]
183pub unsafe extern "C" fn wasmtime_component_linker_instance_add_resource(
184    linker_instance: &mut wasmtime_component_linker_instance_t,
185    name: *const u8,
186    name_len: usize,
187    ty: &wasmtime_component_resource_type_t,
188    callback: wasmtime_component_resource_destructor_t,
189    data: *mut c_void,
190    finalizer: Option<extern "C" fn(*mut c_void)>,
191) -> Option<Box<wasmtime_error_t>> {
192    let name = unsafe { std::slice::from_raw_parts(name, name_len) };
193    let Ok(name) = std::str::from_utf8(name) else {
194        return crate::bad_utf8();
195    };
196
197    let foreign = crate::ForeignData { data, finalizer };
198
199    let result = linker_instance
200        .linker_instance
201        .resource(name, ty.ty, move |ctx, rep| {
202            let _ = &foreign;
203            if let Some(res) = callback(foreign.data, ctx, rep) {
204                return Err((*res).into());
205            }
206            Ok(())
207        });
208
209    crate::handle_result(result, |_| ())
210}
211
212#[unsafe(no_mangle)]
213pub unsafe extern "C" fn wasmtime_component_linker_instance_delete(
214    _linker_instance: Box<wasmtime_component_linker_instance_t>,
215) {
216}