wasmtime_c_api/component/
linker.rs

1use crate::{
2    WasmtimeStoreContextMut, WasmtimeStoreData, wasm_engine_t, wasmtime_component_func_type_t,
3    wasmtime_component_resource_type_t, 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    &wasmtime_component_func_type_t,
103    *mut wasmtime_component_val_t,
104    usize,
105    *mut wasmtime_component_val_t,
106    usize,
107) -> Option<Box<wasmtime_error_t>>;
108
109#[unsafe(no_mangle)]
110pub unsafe extern "C" fn wasmtime_component_linker_instance_add_func(
111    linker_instance: &mut wasmtime_component_linker_instance_t,
112    name: *const u8,
113    name_len: usize,
114    callback: wasmtime_component_func_callback_t,
115    data: *mut c_void,
116    finalizer: Option<extern "C" fn(*mut c_void)>,
117) -> Option<Box<wasmtime_error_t>> {
118    let name = unsafe { std::slice::from_raw_parts(name, name_len) };
119    let Ok(name) = std::str::from_utf8(name) else {
120        return crate::bad_utf8();
121    };
122
123    let foreign = crate::ForeignData { data, finalizer };
124
125    let result = linker_instance
126        .linker_instance
127        .func_new(&name, move |ctx, ty, args, rets| {
128            let _ = &foreign;
129
130            let mut args = args
131                .iter()
132                .map(|x| wasmtime_component_val_t::from(x))
133                .collect::<Vec<_>>();
134
135            let mut c_rets = vec![wasmtime_component_val_t::Bool(false); rets.len()];
136
137            let res = callback(
138                foreign.data,
139                ctx,
140                &ty.into(),
141                args.as_mut_ptr(),
142                args.len(),
143                c_rets.as_mut_ptr(),
144                c_rets.len(),
145            );
146
147            if let Some(res) = res {
148                return Err((*res).into());
149            }
150
151            for (rust_val, c_val) in std::iter::zip(rets, c_rets) {
152                *rust_val = Val::from(&c_val);
153            }
154
155            Ok(())
156        });
157
158    crate::handle_result(result, |_| ())
159}
160
161#[unsafe(no_mangle)]
162#[cfg(feature = "wasi")]
163pub unsafe extern "C" fn wasmtime_component_linker_add_wasip2(
164    linker: &mut wasmtime_component_linker_t,
165) -> Option<Box<wasmtime_error_t>> {
166    let result = wasmtime_wasi::p2::add_to_linker_sync(&mut linker.linker);
167    crate::handle_result(result, |_| ())
168}
169
170#[unsafe(no_mangle)]
171pub unsafe extern "C" fn wasmtime_component_linker_define_unknown_imports_as_traps(
172    linker: &mut wasmtime_component_linker_t,
173    component: &wasmtime_component_t,
174) -> Option<Box<wasmtime_error_t>> {
175    let result = linker
176        .linker
177        .define_unknown_imports_as_traps(&component.component);
178    crate::handle_result(result, |_| ())
179}
180
181pub type wasmtime_component_resource_destructor_t =
182    extern "C" fn(*mut c_void, WasmtimeStoreContextMut<'_>, u32) -> Option<Box<wasmtime_error_t>>;
183
184#[unsafe(no_mangle)]
185pub unsafe extern "C" fn wasmtime_component_linker_instance_add_resource(
186    linker_instance: &mut wasmtime_component_linker_instance_t,
187    name: *const u8,
188    name_len: usize,
189    ty: &wasmtime_component_resource_type_t,
190    callback: wasmtime_component_resource_destructor_t,
191    data: *mut c_void,
192    finalizer: Option<extern "C" fn(*mut c_void)>,
193) -> Option<Box<wasmtime_error_t>> {
194    let name = unsafe { std::slice::from_raw_parts(name, name_len) };
195    let Ok(name) = std::str::from_utf8(name) else {
196        return crate::bad_utf8();
197    };
198
199    let foreign = crate::ForeignData { data, finalizer };
200
201    let result = linker_instance
202        .linker_instance
203        .resource(name, ty.ty, move |ctx, rep| {
204            let _ = &foreign;
205            if let Some(res) = callback(foreign.data, ctx, rep) {
206                return Err((*res).into());
207            }
208            Ok(())
209        });
210
211    crate::handle_result(result, |_| ())
212}
213
214#[unsafe(no_mangle)]
215pub unsafe extern "C" fn wasmtime_component_linker_instance_delete(
216    _linker_instance: Box<wasmtime_component_linker_instance_t>,
217) {
218}