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