1use crate::{
4 ffi::{self},
5 CallingFrame, Instance, WasmEdgeResult, WasmValue,
6};
7use core::ffi::c_void;
8
9use wasmedge_types::{
10 error::{CoreError, FuncError, WasmEdgeError},
11 ValType,
12};
13
14use super::{module::InnerInstance, InnerRef};
15
16pub type SyncFn<Data> = for<'a, 'b, 'c> fn(
17 &'a mut Data,
18 &'b mut Instance,
19 &'c mut CallingFrame,
20 Vec<WasmValue>,
21) -> Result<Vec<WasmValue>, CoreError>;
22
23pub type CustomFnWrapper = unsafe extern "C" fn(
24 key_ptr: *mut c_void,
25 data_ptr: *mut c_void,
26 calling_frame_ctx: *const ffi::WasmEdge_CallingFrameContext,
27 params: *const ffi::WasmEdge_Value,
28 param_len: u32,
29 returns: *mut ffi::WasmEdge_Value,
30 return_len: u32,
31) -> ffi::WasmEdge_Result;
32
33unsafe extern "C" fn wrap_fn<Data>(
35 key_ptr: *mut c_void,
36 data: *mut std::os::raw::c_void,
37 call_frame_ctx: *const ffi::WasmEdge_CallingFrameContext,
38 params: *const ffi::WasmEdge_Value,
39 param_len: u32,
40 returns: *mut ffi::WasmEdge_Value,
41 return_len: u32,
42) -> ffi::WasmEdge_Result {
43 let mut frame = CallingFrame::create(call_frame_ctx);
44 let inst_ctx = ffi::WasmEdge_CallingFrameGetModuleInstance(call_frame_ctx);
46 let mut inst = std::mem::ManuallyDrop::new(Instance {
47 inner: InnerInstance(inst_ctx as _),
48 });
49 let data = &mut *(data as *mut Data);
50
51 let input = if params.is_null() || param_len == 0 {
52 vec![]
53 } else {
54 let raw_input = unsafe { std::slice::from_raw_parts(params, param_len as usize) };
55 raw_input.iter().map(|r| (*r).into()).collect::<Vec<_>>()
56 };
57
58 let return_len = return_len as usize;
59
60 let mut empty_return = [];
61 let raw_returns = if returns.is_null() || return_len == 0 {
62 &mut empty_return
63 } else {
64 unsafe { std::slice::from_raw_parts_mut(returns, return_len) }
65 };
66
67 let real_fn: SyncFn<Data> = std::mem::transmute(key_ptr);
68
69 match real_fn(data, &mut inst, &mut frame, input) {
70 Ok(returns) => {
71 assert!(returns.len() == return_len, "[wasmedge-sys] check the number of returns of host function. Expected: {}, actual: {}", return_len, returns.len());
72 for (idx, wasm_value) in returns.into_iter().enumerate() {
73 raw_returns[idx] = wasm_value.as_raw();
74 }
75 ffi::WasmEdge_Result { Code: 0 }
76 }
77
78 Err(err) => err.into(),
79 }
80}
81
82#[derive(Debug)]
86pub struct Function {
87 pub(crate) inner: InnerFunc,
88}
89impl Function {
90 pub unsafe fn create_sync_func<T>(
112 ty: &wasmedge_types::FuncType,
113 real_fn: SyncFn<T>,
114 data: *mut T,
115 cost: u64,
116 ) -> WasmEdgeResult<Self> {
117 unsafe { Self::create_with_data(ty, real_fn, data, cost) }
118 }
119
120 unsafe fn create_with_data<T>(
139 ty: &wasmedge_types::FuncType,
140 real_fn: SyncFn<T>,
141 data: *mut T,
142 cost: u64,
143 ) -> WasmEdgeResult<Self> {
144 Self::create_with_custom_wrapper(ty, wrap_fn::<T>, real_fn as _, data as _, cost)
145 }
146
147 pub unsafe fn create_with_custom_wrapper(
170 ty: &wasmedge_types::FuncType,
171 fn_wrapper: CustomFnWrapper,
172 real_fn: *mut c_void,
173 data: *mut c_void,
174 cost: u64,
175 ) -> WasmEdgeResult<Self> {
176 let ty: FuncTypeOwn = ty.into();
177 let ctx = ffi::WasmEdge_FunctionInstanceCreateBinding(
178 ty.inner.0,
179 Some(fn_wrapper),
180 real_fn,
181 data,
182 cost,
183 );
184
185 if ctx.is_null() {
186 Err(Box::new(WasmEdgeError::Func(FuncError::Create)))
187 } else {
188 Ok(Self {
189 inner: InnerFunc(ctx),
190 })
191 }
192 }
193
194 pub unsafe fn as_ptr(&self) -> *mut ffi::WasmEdge_FunctionInstanceContext {
198 self.inner.0
199 }
200
201 pub unsafe fn from_raw(ctx: *mut ffi::WasmEdge_FunctionInstanceContext) -> Self {
205 Self {
206 inner: InnerFunc(ctx),
207 }
208 }
209}
210impl Drop for Function {
211 fn drop(&mut self) {
212 unsafe { ffi::WasmEdge_FunctionInstanceDelete(self.inner.0) };
213 }
214}
215
216pub type FuncRef<Ref> = InnerRef<Function, Ref>;
218
219pub trait AsFunc {
220 unsafe fn get_func_raw(&self) -> *mut ffi::WasmEdge_FunctionInstanceContext;
224
225 fn ty(&self) -> Option<wasmedge_types::FuncType>
226 where
227 Self: Sized,
228 {
229 let ty = unsafe { ffi::WasmEdge_FunctionInstanceGetFunctionType(self.get_func_raw()) };
230 if ty.is_null() {
231 None
232 } else {
233 let value = std::mem::ManuallyDrop::new(FuncTypeOwn {
234 inner: InnerFuncType(ty),
235 });
236 Some((&*value).into())
237 }
238 }
239}
240
241impl AsFunc for Function {
242 unsafe fn get_func_raw(&self) -> *mut ffi::WasmEdge_FunctionInstanceContext {
243 self.inner.0
244 }
245}
246impl<F: AsRef<Function>> AsFunc for F {
247 unsafe fn get_func_raw(&self) -> *mut ffi::WasmEdge_FunctionInstanceContext {
248 self.as_ref().get_func_raw()
249 }
250}
251
252#[derive(Debug, Clone, Copy)]
253pub(crate) struct InnerFunc(pub(crate) *mut ffi::WasmEdge_FunctionInstanceContext);
254unsafe impl Send for InnerFunc {}
255unsafe impl Sync for InnerFunc {}
256
257#[derive(Debug)]
258pub(crate) struct FuncTypeOwn {
259 pub(crate) inner: InnerFuncType,
260}
261impl FuncTypeOwn {
262 pub(crate) fn create<I: IntoIterator<Item = ValType>, R: IntoIterator<Item = ValType>>(
274 args: I,
275 returns: R,
276 ) -> WasmEdgeResult<Self> {
277 let param_tys = args
278 .into_iter()
279 .map(|x| x.into())
280 .collect::<Vec<ffi::WasmEdge_ValType>>();
281 let ret_tys = returns
282 .into_iter()
283 .map(|x| x.into())
284 .collect::<Vec<ffi::WasmEdge_ValType>>();
285
286 let ctx = unsafe {
287 ffi::WasmEdge_FunctionTypeCreate(
288 param_tys.as_ptr() as *const _,
289 param_tys.len() as u32,
290 ret_tys.as_ptr() as *const _,
291 ret_tys.len() as u32,
292 )
293 };
294 match ctx.is_null() {
295 true => Err(Box::new(WasmEdgeError::FuncTypeCreate)),
296 false => Ok(Self {
297 inner: InnerFuncType(ctx),
298 }),
299 }
300 }
301}
302impl Drop for FuncTypeOwn {
303 fn drop(&mut self) {
304 unsafe { ffi::WasmEdge_FunctionTypeDelete(self.inner.0 as _) }
305 }
306}
307
308impl FuncTypeOwn {
309 pub(crate) fn params_len(&self) -> u32 {
311 unsafe { ffi::WasmEdge_FunctionTypeGetParametersLength(self.inner.0) }
312 }
313
314 pub(crate) fn params_type_iter(&self) -> impl Iterator<Item = ValType> {
316 let len = self.params_len();
317 let mut types = Vec::with_capacity(len as usize);
318 unsafe {
319 ffi::WasmEdge_FunctionTypeGetParameters(self.inner.0, types.as_mut_ptr(), len);
320 types.set_len(len as usize);
321 }
322
323 types.into_iter().map(Into::into)
324 }
325
326 pub(crate) fn returns_len(&self) -> u32 {
328 unsafe { ffi::WasmEdge_FunctionTypeGetReturnsLength(self.inner.0) }
329 }
330
331 pub(crate) fn returns_type_iter(&self) -> impl Iterator<Item = ValType> {
333 let len = self.returns_len();
334 let mut types = Vec::with_capacity(len as usize);
335 unsafe {
336 ffi::WasmEdge_FunctionTypeGetReturns(self.inner.0, types.as_mut_ptr(), len);
337 types.set_len(len as usize);
338 }
339
340 types.into_iter().map(Into::into)
341 }
342}
343
344impl From<&wasmedge_types::FuncType> for FuncTypeOwn {
345 fn from(ty: &wasmedge_types::FuncType) -> Self {
346 FuncTypeOwn::create(ty.args().to_vec(), ty.returns().to_vec()).expect("[wasmedge-sys] Failed to convert wasmedge_types::FuncType into wasmedge_sys::FuncType.")
347 }
348}
349
350impl From<wasmedge_types::FuncType> for FuncTypeOwn {
351 fn from(ty: wasmedge_types::FuncType) -> Self {
352 (&ty).into()
353 }
354}
355
356impl From<&FuncTypeOwn> for wasmedge_types::FuncType {
357 fn from(ty: &FuncTypeOwn) -> Self {
358 let args = ty.params_type_iter().collect();
359 let returns = ty.returns_type_iter().collect();
360
361 wasmedge_types::FuncType::new(args, returns)
362 }
363}
364
365#[derive(Debug)]
366pub(crate) struct InnerFuncType(pub(crate) *const ffi::WasmEdge_FunctionTypeContext);
367unsafe impl Send for InnerFuncType {}
368unsafe impl Sync for InnerFuncType {}
369
370#[cfg(test)]
371mod tests {
372 use super::*;
373 use crate::{types::WasmValue, AsInstance, Executor, ImportModule};
374
375 use wasmedge_types::{error::CoreExecutionError, FuncType, ValType};
376
377 #[test]
378 fn test_func_type() {
379 {
381 let param_tys = vec![
382 ValType::I32,
383 ValType::I64,
384 ValType::F32,
385 ValType::F64,
386 ValType::V128,
387 ValType::ExternRef,
388 ];
389 let param_len = param_tys.len();
390 let ret_tys = vec![ValType::FuncRef, ValType::ExternRef, ValType::V128];
391 let ret_len = ret_tys.len();
392
393 let result = FuncTypeOwn::create(param_tys, ret_tys);
395 assert!(result.is_ok());
396 let func_ty = result.unwrap();
397
398 assert_eq!(func_ty.params_len(), param_len as u32);
400 let param_tys = func_ty.params_type_iter().collect::<Vec<_>>();
401 assert_eq!(
402 param_tys,
403 vec![
404 ValType::I32,
405 ValType::I64,
406 ValType::F32,
407 ValType::F64,
408 ValType::V128,
409 ValType::ExternRef,
410 ]
411 );
412
413 assert_eq!(func_ty.returns_len(), ret_len as u32);
415 let return_tys = func_ty.returns_type_iter().collect::<Vec<_>>();
416 assert_eq!(
417 return_tys,
418 vec![ValType::FuncRef, ValType::ExternRef, ValType::V128]
419 );
420 }
421
422 {
424 let result = FuncTypeOwn::create([], []);
426 assert!(result.is_ok());
427 let func_ty = result.unwrap();
428
429 assert_eq!(func_ty.params_len(), 0);
430 assert_eq!(func_ty.returns_len(), 0);
431 }
432 }
433
434 #[test]
435 fn test_func_basic() {
436 #[derive(Debug)]
437 struct Data<T, S> {
438 _x: i32,
439 _y: String,
440 _v: Vec<T>,
441 _s: Vec<S>,
442 }
443
444 let data: Data<i32, &str> = Data {
445 _x: 12,
446 _y: "hello".to_string(),
447 _v: vec![1, 2, 3],
448 _s: vec!["macos", "linux", "windows"],
449 };
450
451 fn real_add<T: core::fmt::Debug>(
452 _host_data: &mut Data<i32, &str>,
453 _inst: &mut Instance,
454 _frame: &mut CallingFrame,
455 input: Vec<WasmValue>,
456 ) -> Result<Vec<WasmValue>, CoreError> {
457 println!("Rust: Entering Rust function real_add");
458
459 if input.len() != 2 {
460 return Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch));
461 }
462
463 let a = if input[0].ty() == ValType::I32 {
464 input[0].to_i32()
465 } else {
466 return Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch));
467 };
468
469 let b = if input[1].ty() == ValType::I32 {
470 input[1].to_i32()
471 } else {
472 return Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch));
473 };
474
475 let c = a + b;
476 println!("Rust: calcuating in real_add c: {c:?}");
477
478 println!("Rust: Leaving Rust function real_add");
479 Ok(vec![WasmValue::from_i32(c)])
480 }
481
482 let mut import_module = ImportModule::create("test_module", Box::new(data)).unwrap();
483
484 let func_ty = FuncType::new(vec![ValType::I32; 2], vec![ValType::I32]);
486 let result = unsafe {
488 Function::create_sync_func(
489 &func_ty,
490 real_add::<Data<i32, &str>>,
491 import_module.get_host_data_mut(),
492 0,
493 )
494 };
495 assert!(result.is_ok());
496 let host_func = result.unwrap();
497
498 let result = host_func.ty();
500 assert!(result.is_some());
501 let ty = result.unwrap();
502
503 assert_eq!(ty.args_len(), 2);
505 assert_eq!(ty.args(), &[ValType::I32; 2]);
506
507 assert_eq!(ty.returns_len(), 1);
509 assert_eq!(ty.returns(), &[ValType::I32]);
510
511 import_module.add_func("add", host_func);
512
513 let result = Executor::create(None, None);
515 assert!(result.is_ok());
516 let mut executor = result.unwrap();
517
518 let mut add_func = import_module.get_func_mut("add").unwrap();
519
520 let result = executor.call_func(
521 &mut add_func,
522 vec![WasmValue::from_i32(1), WasmValue::from_i32(2)],
523 );
524
525 assert!(result.is_ok());
526 let returns = result.unwrap();
527 assert_eq!(returns[0].to_i32(), 3);
528 }
529}