wamr_rust_sdk/
host_function.rs

1/*
2 * Copyright (C) 2019 Intel Corporation. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4 */
5
6/// This is a wrapper of a host defined(Rust) function.
7use std::ffi::{c_void, CString};
8use std::ptr;
9
10use wamr_sys::NativeSymbol;
11
12#[allow(dead_code)]
13#[derive(Debug)]
14struct HostFunction {
15    function_name: CString,
16    function_ptr: *mut c_void,
17}
18
19#[derive(Debug)]
20pub struct HostFunctionList {
21    pub module_name: CString,
22    // keep ownership of the content of `native_symbols`
23    host_functions: Vec<HostFunction>,
24    pub native_symbols: Vec<NativeSymbol>,
25}
26
27impl HostFunctionList {
28    pub fn new(module_name: &str) -> Self {
29        HostFunctionList {
30            module_name: CString::new(module_name).unwrap(),
31            host_functions: Vec::new(),
32            native_symbols: Vec::new(),
33        }
34    }
35
36    pub fn register_host_function(&mut self, function_name: &str, function_ptr: *mut c_void) {
37        self.host_functions.push(HostFunction {
38            function_name: CString::new(function_name).unwrap(),
39            function_ptr,
40        });
41
42        let last = self.host_functions.last().unwrap();
43        self.native_symbols
44            .push(pack_host_function(&(last.function_name), function_ptr));
45    }
46
47    pub fn get_native_symbols(&mut self) -> &mut Vec<NativeSymbol> {
48        &mut self.native_symbols
49    }
50
51    pub fn get_module_name(&mut self) -> &CString {
52        &self.module_name
53    }
54}
55
56pub fn pack_host_function(function_name: &CString, function_ptr: *mut c_void) -> NativeSymbol {
57    NativeSymbol {
58        symbol: function_name.as_ptr(),
59        func_ptr: function_ptr,
60        signature: ptr::null(),
61        attachment: ptr::null_mut(),
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use crate::{
69        function::Function, instance::Instance, module::Module, runtime::Runtime, value::WasmValue,
70    };
71    use std::env;
72    use std::path::PathBuf;
73
74    extern "C" fn extra() -> i32 {
75        100
76    }
77
78    #[test]
79    #[ignore]
80    fn test_host_function() {
81        let runtime = Runtime::builder()
82            .use_system_allocator()
83            .register_host_function("extra", extra as *mut c_void)
84            .build()
85            .unwrap();
86
87        let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
88        d.push("resources/test");
89        d.push("add_extra_wasm32_wasi.wasm");
90        let module = Module::from_file(&runtime, d.as_path());
91        assert!(module.is_ok());
92        let module = module.unwrap();
93
94        let instance = Instance::new(&runtime, &module, 1024 * 64);
95        assert!(instance.is_ok());
96        let instance: &Instance = &instance.unwrap();
97
98        let function = Function::find_export_func(instance, "add");
99        assert!(function.is_ok());
100        let function = function.unwrap();
101
102        let params: Vec<WasmValue> = vec![WasmValue::I32(8), WasmValue::I32(8)];
103        let result = function.call(instance, &params);
104        assert_eq!(result.unwrap(), vec![WasmValue::I32(116)]);
105    }
106}