wasmtime_c_api/component/
linker.rs

1use std::ffi::c_void;
2
3use wasmtime::component::{Instance, Linker, LinkerInstance, Val};
4
5use crate::{
6    WasmtimeStoreContextMut, WasmtimeStoreData, wasm_engine_t, wasmtime_error_t, wasmtime_module_t,
7};
8
9use super::{wasmtime_component_t, wasmtime_component_val_t};
10
11#[repr(transparent)]
12pub struct wasmtime_component_linker_t {
13    pub(crate) linker: Linker<WasmtimeStoreData>,
14}
15
16#[repr(transparent)]
17pub struct wasmtime_component_linker_instance_t<'a> {
18    pub(crate) linker_instance: LinkerInstance<'a, WasmtimeStoreData>,
19}
20
21#[unsafe(no_mangle)]
22pub unsafe extern "C" fn wasmtime_component_linker_new(
23    engine: &wasm_engine_t,
24) -> Box<wasmtime_component_linker_t> {
25    Box::new(wasmtime_component_linker_t {
26        linker: Linker::new(&engine.engine),
27    })
28}
29
30#[unsafe(no_mangle)]
31pub unsafe extern "C" fn wasmtime_component_linker_root(
32    linker: &mut wasmtime_component_linker_t,
33) -> Box<wasmtime_component_linker_instance_t<'_>> {
34    Box::new(wasmtime_component_linker_instance_t {
35        linker_instance: linker.linker.root(),
36    })
37}
38
39#[unsafe(no_mangle)]
40pub unsafe extern "C" fn wasmtime_component_linker_instantiate(
41    linker: &wasmtime_component_linker_t,
42    context: WasmtimeStoreContextMut<'_>,
43    component: &wasmtime_component_t,
44    instance_out: &mut Instance,
45) -> Option<Box<wasmtime_error_t>> {
46    let result = linker.linker.instantiate(context, &component.component);
47    crate::handle_result(result, |instance| *instance_out = instance)
48}
49
50#[unsafe(no_mangle)]
51pub unsafe extern "C" fn wasmtime_component_linker_delete(
52    _linker: Box<wasmtime_component_linker_t>,
53) {
54}
55
56#[unsafe(no_mangle)]
57pub unsafe extern "C" fn wasmtime_component_linker_instance_add_instance<'a>(
58    linker_instance: &'a mut wasmtime_component_linker_instance_t<'a>,
59    name: *const u8,
60    name_len: usize,
61    linker_instance_out: &mut *mut wasmtime_component_linker_instance_t<'a>,
62) -> Option<Box<wasmtime_error_t>> {
63    let name = unsafe { std::slice::from_raw_parts(name, name_len) };
64    let Ok(name) = std::str::from_utf8(name) else {
65        return crate::bad_utf8();
66    };
67
68    let result = linker_instance.linker_instance.instance(&name);
69    crate::handle_result(result, |linker_instance| {
70        *linker_instance_out = Box::into_raw(Box::new(wasmtime_component_linker_instance_t {
71            linker_instance,
72        }));
73    })
74}
75
76#[unsafe(no_mangle)]
77pub unsafe extern "C" fn wasmtime_component_linker_instance_add_module(
78    linker_instance: &mut wasmtime_component_linker_instance_t,
79    name: *const u8,
80    name_len: usize,
81    module: &wasmtime_module_t,
82) -> Option<Box<wasmtime_error_t>> {
83    let name = unsafe { std::slice::from_raw_parts(name, name_len) };
84    let Ok(name) = std::str::from_utf8(name) else {
85        return crate::bad_utf8();
86    };
87
88    let result = linker_instance
89        .linker_instance
90        .module(&name, &module.module);
91
92    crate::handle_result(result, |_| ())
93}
94
95pub type wasmtime_component_func_callback_t = extern "C" fn(
96    *mut c_void,
97    WasmtimeStoreContextMut<'_>,
98    *const wasmtime_component_val_t,
99    usize,
100    *mut wasmtime_component_val_t,
101    usize,
102) -> Option<Box<wasmtime_error_t>>;
103
104#[unsafe(no_mangle)]
105pub unsafe extern "C" fn wasmtime_component_linker_instance_add_func(
106    linker_instance: &mut wasmtime_component_linker_instance_t,
107    name: *const u8,
108    name_len: usize,
109    callback: wasmtime_component_func_callback_t,
110    data: *mut c_void,
111    finalizer: Option<extern "C" fn(*mut c_void)>,
112) -> Option<Box<wasmtime_error_t>> {
113    let name = unsafe { std::slice::from_raw_parts(name, name_len) };
114    let Ok(name) = std::str::from_utf8(name) else {
115        return crate::bad_utf8();
116    };
117
118    let foreign = crate::ForeignData { data, finalizer };
119
120    let result = linker_instance
121        .linker_instance
122        .func_new(&name, move |ctx, args, rets| {
123            let _ = &foreign;
124
125            let args = args
126                .iter()
127                .map(|x| wasmtime_component_val_t::from(x))
128                .collect::<Vec<_>>();
129
130            let mut c_rets = vec![wasmtime_component_val_t::Bool(false); rets.len()];
131
132            let res = callback(
133                foreign.data,
134                ctx,
135                args.as_ptr(),
136                args.len(),
137                c_rets.as_mut_ptr(),
138                c_rets.len(),
139            );
140
141            if let Some(res) = res {
142                return Err((*res).into());
143            }
144
145            for (rust_val, c_val) in std::iter::zip(rets, c_rets) {
146                *rust_val = Val::from(&c_val);
147            }
148
149            Ok(())
150        });
151
152    crate::handle_result(result, |_| ())
153}
154
155#[unsafe(no_mangle)]
156pub unsafe extern "C" fn wasmtime_component_linker_instance_delete(
157    _linker_instance: Box<wasmtime_component_linker_instance_t>,
158) {
159}