wasmtime_c_api/component/
linker.rs1use 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}