wasmtime_c_api/component/
linker.rs1use 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#[cfg(feature = "component-model-async")]
162pub type wasmtime_component_func_async_callback_t = extern "C" fn(
163 *mut c_void,
164 WasmtimeStoreContextMut<'_>,
165 &wasmtime_component_func_type_t,
166 *mut wasmtime_component_val_t,
167 usize,
168 *mut wasmtime_component_val_t,
169 usize,
170 &mut Option<Box<wasmtime_error_t>>,
171 &mut crate::wasmtime_async_continuation_t,
172);
173
174#[unsafe(no_mangle)]
175#[cfg(feature = "component-model-async")]
176pub unsafe extern "C" fn wasmtime_component_linker_instance_add_func_async(
177 linker_instance: &mut wasmtime_component_linker_instance_t,
178 name: *const u8,
179 name_len: usize,
180 callback: wasmtime_component_func_async_callback_t,
181 data: *mut c_void,
182 finalizer: Option<extern "C" fn(*mut c_void)>,
183) -> Option<Box<wasmtime_error_t>> {
184 let name = unsafe { std::slice::from_raw_parts(name, name_len) };
185 let Ok(name) = std::str::from_utf8(name) else {
186 return crate::bad_utf8();
187 };
188
189 let foreign = crate::ForeignData { data, finalizer };
190
191 let result =
192 linker_instance
193 .linker_instance
194 .func_new_async(&name, move |ctx, ty, args, rets| {
195 let _ = &foreign;
196
197 let mut c_args = args
198 .iter()
199 .map(|x| wasmtime_component_val_t::from(x))
200 .collect::<Vec<_>>();
201
202 let mut c_rets = vec![wasmtime_component_val_t::Bool(false); rets.len()];
203
204 let mut err = None;
205 extern "C" fn panic_callback(_: *mut c_void) -> bool {
206 panic!("callback must be set")
207 }
208 let mut continuation = crate::wasmtime_async_continuation_t {
209 callback: panic_callback,
210 env: std::ptr::null_mut(),
211 finalizer: None,
212 };
213 callback(
214 foreign.data,
215 ctx,
216 &ty.into(),
217 c_args.as_mut_ptr(),
218 c_args.len(),
219 c_rets.as_mut_ptr(),
220 c_rets.len(),
221 &mut err,
222 &mut continuation,
223 );
224
225 if let Some(err) = err {
226 return Box::new(async { Err((*err).into()) });
227 }
228
229 Box::new(async move {
230 continuation.await;
231 for (rust_val, c_val) in std::iter::zip(rets, c_rets) {
232 *rust_val = Val::from(&c_val);
233 }
234 Ok(())
235 })
236 });
237
238 crate::handle_result(result, |_| ())
239}
240
241#[unsafe(no_mangle)]
242#[cfg(feature = "wasi")]
243pub unsafe extern "C" fn wasmtime_component_linker_add_wasip2(
244 linker: &mut wasmtime_component_linker_t,
245) -> Option<Box<wasmtime_error_t>> {
246 let result = wasmtime_wasi::p2::add_to_linker_sync(&mut linker.linker);
247 crate::handle_result(result, |_| ())
248}
249
250#[unsafe(no_mangle)]
251#[cfg(feature = "wasi-http")]
252pub unsafe extern "C" fn wasmtime_component_linker_add_wasi_http(
253 linker: &mut wasmtime_component_linker_t,
254) -> Option<Box<wasmtime_error_t>> {
255 let result = wasmtime_wasi_http::p2::add_only_http_to_linker_sync(&mut linker.linker);
256 crate::handle_result(result, |_| ())
257}
258
259#[unsafe(no_mangle)]
260#[cfg(feature = "component-model-async")]
261pub unsafe extern "C" fn wasmtime_component_linker_instantiate_async<'a>(
262 linker: &'a wasmtime_component_linker_t,
263 mut context: WasmtimeStoreContextMut<'a>,
264 component: &'a wasmtime_component_t,
265 instance_out: &'a mut Instance,
266 err_ret: &'a mut *mut wasmtime_error_t,
267) -> Box<crate::wasmtime_call_future_t<'a>> {
268 let fut = Box::pin(async move {
269 match linker
270 .linker
271 .instantiate_async(&mut context, &component.component)
272 .await
273 {
274 Ok(instance) => *instance_out = instance,
275 Err(err) => {
276 *err_ret = Box::into_raw(Box::new(wasmtime_error_t::from(err)));
277 }
278 }
279 });
280 Box::new(crate::wasmtime_call_future_t::new(fut))
281}
282
283#[unsafe(no_mangle)]
284#[cfg(all(feature = "wasi", feature = "component-model-async"))]
285pub unsafe extern "C" fn wasmtime_component_linker_add_wasip2_async(
286 linker: &mut wasmtime_component_linker_t,
287) -> Option<Box<wasmtime_error_t>> {
288 let result = wasmtime_wasi::p2::add_to_linker_async(&mut linker.linker);
289 crate::handle_result(result, |_| ())
290}
291
292#[unsafe(no_mangle)]
293#[cfg(all(feature = "wasi-http", feature = "component-model-async"))]
294pub unsafe extern "C" fn wasmtime_component_linker_add_wasi_http_async(
295 linker: &mut wasmtime_component_linker_t,
296) -> Option<Box<wasmtime_error_t>> {
297 let result = wasmtime_wasi_http::p2::add_only_http_to_linker_async(&mut linker.linker);
298 crate::handle_result(result, |_| ())
299}
300
301#[unsafe(no_mangle)]
302pub unsafe extern "C" fn wasmtime_component_linker_define_unknown_imports_as_traps(
303 linker: &mut wasmtime_component_linker_t,
304 component: &wasmtime_component_t,
305) -> Option<Box<wasmtime_error_t>> {
306 let result = linker
307 .linker
308 .define_unknown_imports_as_traps(&component.component);
309 crate::handle_result(result, |_| ())
310}
311
312pub type wasmtime_component_resource_destructor_t =
313 extern "C" fn(*mut c_void, WasmtimeStoreContextMut<'_>, u32) -> Option<Box<wasmtime_error_t>>;
314
315#[unsafe(no_mangle)]
316pub unsafe extern "C" fn wasmtime_component_linker_instance_add_resource(
317 linker_instance: &mut wasmtime_component_linker_instance_t,
318 name: *const u8,
319 name_len: usize,
320 ty: &wasmtime_component_resource_type_t,
321 callback: wasmtime_component_resource_destructor_t,
322 data: *mut c_void,
323 finalizer: Option<extern "C" fn(*mut c_void)>,
324) -> Option<Box<wasmtime_error_t>> {
325 let name = unsafe { std::slice::from_raw_parts(name, name_len) };
326 let Ok(name) = std::str::from_utf8(name) else {
327 return crate::bad_utf8();
328 };
329
330 let foreign = crate::ForeignData { data, finalizer };
331
332 let result = linker_instance
333 .linker_instance
334 .resource(name, ty.ty, move |ctx, rep| {
335 let _ = &foreign;
336 if let Some(res) = callback(foreign.data, ctx, rep) {
337 return Err((*res).into());
338 }
339 Ok(())
340 });
341
342 crate::handle_result(result, |_| ())
343}
344
345#[unsafe(no_mangle)]
346pub unsafe extern "C" fn wasmtime_component_linker_instance_delete(
347 _linker_instance: Box<wasmtime_component_linker_instance_t>,
348) {
349}