itachaaa opened issue #9017:
I know that there are some
wasi_snapshot_preview1::fd_write
related descriptions in the recent issue: 8521, 7697, and I addedadd_to_linker_sync
in my code. However, the type does not match and the compilation fails. Here are the details,I want to implement a small program that calls the cache interface in wasm.Running it directly throws an exception like this:
thread 'main' panicked at src/main.rs:62:67: called `Result::unwrap()` on an `Err` value: unknown import: `wasi_snapshot_preview1::fd_write` has not been defined note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
When I added
add_to_linker_sync
the compile Error:error[E0308]: mismatched types --> src/main.rs:62:39 | 62 | wasmtime_wasi::add_to_linker_sync(&mut linker).unwrap(); | --------------------------------- ^^^^^^^^^^^ expected `&mut Linker<_>`, found `&mut Linker<Arc<Mutex<KvStore>>>` | | | arguments to this function are incorrect | = note: expected mutable reference `&mut wasmtime::component::Linker<_>` found mutable reference `&mut wasmtime::Linker<Arc<Mutex<KvStore>>>`
wasm_runner:
use wasmtime::*; use kv_store::{create_kv_store, SharedKvStore}; fn main() { let mut config = Config::new(); Config::async_support(&mut config, false); config.wasm_backtrace_details(WasmBacktraceDetails::Enable); config.wasm_component_model(true); let engine = Engine::new(&config).unwrap(); let kv_store = create_kv_store(); let mut store = Store::new(&engine, kv_store.clone()); // Load the WebAssembly module // let caller_wasm = fs::read("../caller/target/wasm32-wasi/release/caller.wasm").unwrap(); let caller_module = Module::from_file(&engine, "../caller/target/wasm32-wasi/release/caller.wasm").unwrap(); // Create a new Linker to link WASI functions let mut linker = Linker::new(&engine); // Register the `get` function linker.func_wrap("env", "kv_get", move |mut caller: Caller<'_, SharedKvStore>, ptr: i32, len: i32, result_ptr: i32| -> i32 { let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); let data = memory.data(&caller); // Immutable access to memory to read key let key = &data[ptr as usize..(ptr + len) as usize]; let key_str = std::str::from_utf8(key).unwrap(); // Perform lookup in the shared KV store let value_opt = caller.data().lock().unwrap().get(key_str); // Mutable access to memory to write result let data_mut = memory.data_mut(&mut caller); if let Some(value) = value_opt { let value_bytes = value.as_bytes(); let result_slice = &mut data_mut[result_ptr as usize..(result_ptr as usize + value_bytes.len())]; result_slice.copy_from_slice(value_bytes); value_bytes.len() as i32 } else { -1 } }).unwrap(); // Register the `set` function linker.func_wrap("env", "kv_set", move |mut caller: Caller<'_, SharedKvStore>, key_ptr: i32, key_len: i32, value_ptr: i32, value_len: i32| { let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); let data = memory.data(&caller); // Immutable access to memory to read key and value let key = &data[key_ptr as usize..(key_ptr + key_len) as usize]; let value = &data[value_ptr as usize..(value_ptr + value_len) as usize]; let key_str = std::str::from_utf8(key).unwrap(); let value_str = std::str::from_utf8(value).unwrap(); // Perform write operation in the shared KV store caller.data().lock().unwrap().set(key_str, value_str); }) .unwrap(); // Instantiate the module // wasmtime_wasi::add_to_linker_sync(&mut linker).unwrap(); let instance = linker.instantiate(&mut store, &caller_module).unwrap(); // Call WebAssembly functions let set_key_value = instance.get_func(&mut store, "set_key_value").unwrap().typed::<(i32, i32), ()>(&store).unwrap(); set_key_value.call(&mut store, (0, 0)).unwrap(); let get_key_value = instance.get_func(&mut store, "get_key_value").unwrap().typed::<i32, i32>(&store).unwrap(); let result = get_key_value.call(&mut store, 0).unwrap(); println!("Got value from KV store: {}", result); }
[package] name = "wasm_runner" version = "0.1.0" edition = "2021" [dependencies] wasmtime = "23.0.1" wasmtime-wasi = "23.0.1" kv_store = { path = "../kv_store" }
caller:
extern "C" { pub fn kv_get(ptr: *const u8, len: usize, result_ptr: *mut u8) -> i32; pub fn kv_set(key_ptr: *const u8, key_len: usize, value_ptr: *const u8, value_len: usize); } #[no_mangle] pub unsafe fn set_key_value(key: &str, value: &str) { unsafe { kv_set(key.as_ptr(), key.len(), value.as_ptr(), value.len()); } } #[no_mangle] pub unsafe fn get_key_value(key: &str) -> Option<String> { let mut result = vec![0u8; 100]; // 假设结果长度不会超过100字节 let result_ptr = result.as_mut_ptr(); let len = unsafe { kv_get(key.as_ptr(), key.len(), result_ptr) }; if len >= 0 { Some(String::from_utf8(result[..len as usize].to_vec()).unwrap()) } else { None } }
[package] name = "caller" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"]
use std::collections::HashMap; use std::sync::{Arc, Mutex}; pub struct KvStore { map: HashMap<String, String>, } impl KvStore { pub fn new() -> Self { KvStore { map: HashMap::new(), } } pub fn get(&self, key: &str) -> Option<String> { self.map.get(key).cloned() } pub fn set(&mut self, key: &str, value: &str) { self.map.insert(key.to_string(), value.to_string()); } } pub type SharedKvStore = Arc<Mutex<KvStore>>; pub fn create_kv_store() -> SharedKvStore { Arc::new(Mutex::new(KvStore::new())) }
alexcrichton commented on issue #9017:
You're currently working at the core wasm abstraction layer, not the component layer, meaning you want the
preview1
module.Even with that though your code contains:
#[no_mangle] pub unsafe fn set_key_value(key: &str, value: &str) { ... }
which is unlikely to be what you want.
I'd recommend reading over examples/documentation about passing strings into WebAssembly and possible reading up on the component model which would enable that use case more cleanly
itachaaa commented on issue #9017:
You're currently working at the core wasm abstraction layer, not the component layer, meaning you want the
preview1
module.您目前使用的是核心 wasm 抽象层,而不是组件层,这意味着您需要preview1
模块。Even with that though your code contains:即便如此,您的代码中仍包含
#[no_mangle] pub unsafe fn set_key_value(key: &str, value: &str) { ... }
which is unlikely to be what you want.这不可能是你想要的。
I'd recommend reading over examples/documentation about passing strings into WebAssembly and possible reading up on the component model which would enable that use case more cleanly我建议你阅读有关向 WebAssembly 传递字符串的示例/文档,并在可能的情况下阅读有关组件模型的内容,这样就能更简洁地实现该用例。
Thanks,it helps a lot about params passing. I changed my code, however,
wasi_snapshot_preview1::fd_write
has not been defined` still happed.
itachaaa edited a comment on issue #9017:
You're currently working at the core wasm abstraction layer, not the component layer, meaning you want the
preview1
module.您目前使用的是核心 wasm 抽象层,而不是组件层,这意味着您需要preview1
模块。Even with that though your code contains:即便如此,您的代码中仍包含
#[no_mangle] pub unsafe fn set_key_value(key: &str, value: &str) { ... }
which is unlikely to be what you want.这不可能是你想要的。
I'd recommend reading over examples/documentation about passing strings into WebAssembly and possible reading up on the component model which would enable that use case more cleanly我建议你阅读有关向 WebAssembly 传递字符串的示例/文档,并在可能的情况下阅读有关组件模型的内容,这样就能更简洁地实现该用例。
Thanks,it helps a lot about params passing. I changed my code, however,
wasi_snapshot_preview1::fd_write
has not been defined` still happed.changed caller code:
extern "C" { pub fn kv_get(ptr: *const u8, len: i32, result_ptr: i32) -> i32; pub fn kv_set(key_ptr: *const u8, key_len: i32, value_ptr: *const u8, value_len: i32); } #[no_mangle] pub unsafe fn set_key_value() { unsafe { kv_set(KEY.as_ptr(), KEY.len() as i32, VALUE.as_ptr(), VALUE.len() as i32); } } #[no_mangle] pub unsafe fn get_key_value() { let mut result = vec![0u8; 100]; // 假设结果长度不会超过100字节 let result_ptr = result.as_mut_ptr(); let len = unsafe { kv_get(KEY.as_ptr(), KEY.len() as i32, result_ptr as i32) }; if len > 0 { println!("got value: {}", String::from_utf8(result[..len as usize].to_vec()).unwrap()); } else { println!("failed get value."); } } static KEY: &str = "Name"; static VALUE: &str = "World";
changed main code:
use wasmtime::*; use kv_store::{create_kv_store, SharedKvStore}; fn main() { let mut config = Config::new(); Config::async_support(&mut config, false); config.wasm_backtrace_details(WasmBacktraceDetails::Enable); config.wasm_component_model(true); let engine = Engine::new(&config).unwrap(); let kv_store = create_kv_store(); let mut store = Store::new(&engine, kv_store.clone()); // Load the WebAssembly module let caller_module = Module::from_file(&engine, "../caller/target/wasm32-wasi/release/caller.wasm").unwrap(); // Create a new Linker to link WASI functions let mut linker = Linker::new(&engine); // Register the `get` function linker.func_wrap("env", "kv_get", move |mut caller: Caller<'_, SharedKvStore>, ptr: i32, len: i32, result_ptr: i32| -> i32 { let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); let data = memory.data(&caller); // Immutable access to memory to read key let key = &data[ptr as usize..(ptr + len) as usize]; let key_str = std::str::from_utf8(key).unwrap(); // Perform lookup in the shared KV store let value_opt = caller.data().lock().unwrap().get(key_str); // Mutable access to memory to write result let data_mut = memory.data_mut(&mut caller); if let Some(value) = value_opt { let value_bytes = value.as_bytes(); let result_slice = &mut data_mut[result_ptr as usize..(result_ptr as usize + value_bytes.len())]; result_slice.copy_from_slice(value_bytes); value_bytes.len() as i32 } else { -1 } }).unwrap(); // Register the `set` function linker.func_wrap("env", "kv_set", move |mut caller: Caller<'_, SharedKvStore>, key_ptr: i32, key_len: i32, value_ptr: i32, value_len: i32| { let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); let data = memory.data(&caller); // Immutable access to memory to read key and value println!("got key_len: {}, key_ptr: {}", key_len, key_ptr); let value = &data[value_ptr as usize..(value_ptr + value_len) as usize]; let key = &data[key_ptr as usize..(key_ptr + key_len) as usize]; let key_str = std::str::from_utf8(key).unwrap(); assert_eq!(key_str, "Name"); let value_str = std::str::from_utf8(value).unwrap(); // Perform write operation in the shared KV store caller.data().lock().unwrap().set(key_str, value_str); }) .unwrap(); // Instantiate the module let instance = linker.instantiate(&mut store, &caller_module).unwrap(); // Call WebAssembly functions let set_key_value = instance.get_func(&mut store, "set_key_value").unwrap().typed::<(), ()>(&store).unwrap(); set_key_value.call(&mut store, ()).unwrap(); let get_key_value = instance.get_func(&mut store, "get_key_value").unwrap().typed::<(), ()>(&store).unwrap(); get_key_value.call(&mut store, ()).unwrap(); }
itachaaa edited a comment on issue #9017:
You're currently working at the core wasm abstraction layer, not the component layer, meaning you want the
preview1
module.您目前使用的是核心 wasm 抽象层,而不是组件层,这意味着您需要preview1
模块。Even with that though your code contains:即便如此,您的代码中仍包含
#[no_mangle] pub unsafe fn set_key_value(key: &str, value: &str) { ... }
which is unlikely to be what you want.这不可能是你想要的。
I'd recommend reading over examples/documentation about passing strings into WebAssembly and possible reading up on the component model which would enable that use case more cleanly我建议你阅读有关向 WebAssembly 传递字符串的示例/文档,并在可能的情况下阅读有关组件模型的内容,这样就能更简洁地实现该用例。
Thanks,it helps a lot about params passing. I changed my code without passing string params, however,
wasi_snapshot_preview1::fd_write
has not been defined` still happed.changed caller code:
extern "C" { pub fn kv_get(ptr: *const u8, len: i32, result_ptr: i32) -> i32; pub fn kv_set(key_ptr: *const u8, key_len: i32, value_ptr: *const u8, value_len: i32); } #[no_mangle] pub unsafe fn set_key_value() { unsafe { kv_set(KEY.as_ptr(), KEY.len() as i32, VALUE.as_ptr(), VALUE.len() as i32); } } #[no_mangle] pub unsafe fn get_key_value() { let mut result = vec![0u8; 100]; // 假设结果长度不会超过100字节 let result_ptr = result.as_mut_ptr(); let len = unsafe { kv_get(KEY.as_ptr(), KEY.len() as i32, result_ptr as i32) }; if len > 0 { println!("got value: {}", String::from_utf8(result[..len as usize].to_vec()).unwrap()); } else { println!("failed get value."); } } static KEY: &str = "Name"; static VALUE: &str = "World";
changed main code:
use wasmtime::*; use kv_store::{create_kv_store, SharedKvStore}; fn main() { let mut config = Config::new(); Config::async_support(&mut config, false); config.wasm_backtrace_details(WasmBacktraceDetails::Enable); config.wasm_component_model(true); let engine = Engine::new(&config).unwrap(); let kv_store = create_kv_store(); let mut store = Store::new(&engine, kv_store.clone()); // Load the WebAssembly module let caller_module = Module::from_file(&engine, "../caller/target/wasm32-wasi/release/caller.wasm").unwrap(); // Create a new Linker to link WASI functions let mut linker = Linker::new(&engine); // Register the `get` function linker.func_wrap("env", "kv_get", move |mut caller: Caller<'_, SharedKvStore>, ptr: i32, len: i32, result_ptr: i32| -> i32 { let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); let data = memory.data(&caller); // Immutable access to memory to read key let key = &data[ptr as usize..(ptr + len) as usize]; let key_str = std::str::from_utf8(key).unwrap(); // Perform lookup in the shared KV store let value_opt = caller.data().lock().unwrap().get(key_str); // Mutable access to memory to write result let data_mut = memory.data_mut(&mut caller); if let Some(value) = value_opt { let value_bytes = value.as_bytes(); let result_slice = &mut data_mut[result_ptr as usize..(result_ptr as usize + value_bytes.len())]; result_slice.copy_from_slice(value_bytes); value_bytes.len() as i32 } else { -1 } }).unwrap(); // Register the `set` function linker.func_wrap("env", "kv_set", move |mut caller: Caller<'_, SharedKvStore>, key_ptr: i32, key_len: i32, value_ptr: i32, value_len: i32| { let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); let data = memory.data(&caller); // Immutable access to memory to read key and value println!("got key_len: {}, key_ptr: {}", key_len, key_ptr); let value = &data[value_ptr as usize..(value_ptr + value_len) as usize]; let key = &data[key_ptr as usize..(key_ptr + key_len) as usize]; let key_str = std::str::from_utf8(key).unwrap(); assert_eq!(key_str, "Name"); let value_str = std::str::from_utf8(value).unwrap(); // Perform write operation in the shared KV store caller.data().lock().unwrap().set(key_str, value_str); }) .unwrap(); // Instantiate the module let instance = linker.instantiate(&mut store, &caller_module).unwrap(); // Call WebAssembly functions let set_key_value = instance.get_func(&mut store, "set_key_value").unwrap().typed::<(), ()>(&store).unwrap(); set_key_value.call(&mut store, ()).unwrap(); let get_key_value = instance.get_func(&mut store, "get_key_value").unwrap().typed::<(), ()>(&store).unwrap(); get_key_value.call(&mut store, ()).unwrap(); }
itachaaa edited a comment on issue #9017:
You're currently working at the core wasm abstraction layer, not the component layer, meaning you want the
preview1
module.Even with that though your code contains:
#[no_mangle] pub unsafe fn set_key_value(key: &str, value: &str) { ... }
which is unlikely to be what you want.
I'd recommend reading over examples/documentation about passing strings into WebAssembly and possible reading up on the component model which would enable that use case more cleanly
Thanks,it helps a lot about params passing. I changed my code without passing string params, however,
wasi_snapshot_preview1::fd_write
has not been defined` still happed.changed caller code:
extern "C" { pub fn kv_get(ptr: *const u8, len: i32, result_ptr: i32) -> i32; pub fn kv_set(key_ptr: *const u8, key_len: i32, value_ptr: *const u8, value_len: i32); } #[no_mangle] pub unsafe fn set_key_value() { unsafe { kv_set(KEY.as_ptr(), KEY.len() as i32, VALUE.as_ptr(), VALUE.len() as i32); } } #[no_mangle] pub unsafe fn get_key_value() { let mut result = vec![0u8; 100]; let result_ptr = result.as_mut_ptr(); let len = unsafe { kv_get(KEY.as_ptr(), KEY.len() as i32, result_ptr as i32) }; if len > 0 { println!("got value: {}", String::from_utf8(result[..len as usize].to_vec()).unwrap()); } else { println!("failed get value."); } } static KEY: &str = "Name"; static VALUE: &str = "World";
changed main code:
use wasmtime::*; use kv_store::{create_kv_store, SharedKvStore}; fn main() { let mut config = Config::new(); Config::async_support(&mut config, false); config.wasm_backtrace_details(WasmBacktraceDetails::Enable); config.wasm_component_model(true); let engine = Engine::new(&config).unwrap(); let kv_store = create_kv_store(); let mut store = Store::new(&engine, kv_store.clone()); // Load the WebAssembly module let caller_module = Module::from_file(&engine, "../caller/target/wasm32-wasi/release/caller.wasm").unwrap(); // Create a new Linker to link WASI functions let mut linker = Linker::new(&engine); // Register the `get` function linker.func_wrap("env", "kv_get", move |mut caller: Caller<'_, SharedKvStore>, ptr: i32, len: i32, result_ptr: i32| -> i32 { let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); let data = memory.data(&caller); // Immutable access to memory to read key let key = &data[ptr as usize..(ptr + len) as usize]; let key_str = std::str::from_utf8(key).unwrap(); // Perform lookup in the shared KV store let value_opt = caller.data().lock().unwrap().get(key_str); // Mutable access to memory to write result let data_mut = memory.data_mut(&mut caller); if let Some(value) = value_opt { let value_bytes = value.as_bytes(); let result_slice = &mut data_mut[result_ptr as usize..(result_ptr as usize + value_bytes.len())]; result_slice.copy_from_slice(value_bytes); value_bytes.len() as i32 } else { -1 } }).unwrap(); // Register the `set` function linker.func_wrap("env", "kv_set", move |mut caller: Caller<'_, SharedKvStore>, key_ptr: i32, key_len: i32, value_ptr: i32, value_len: i32| { let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); let data = memory.data(&caller); // Immutable access to memory to read key and value println!("got key_len: {}, key_ptr: {}", key_len, key_ptr); let value = &data[value_ptr as usize..(value_ptr + value_len) as usize]; let key = &data[key_ptr as usize..(key_ptr + key_len) as usize]; let key_str = std::str::from_utf8(key).unwrap(); assert_eq!(key_str, "Name"); let value_str = std::str::from_utf8(value).unwrap(); // Perform write operation in the shared KV store caller.data().lock().unwrap().set(key_str, value_str); }) .unwrap(); // Instantiate the module let instance = linker.instantiate(&mut store, &caller_module).unwrap(); // Call WebAssembly functions let set_key_value = instance.get_func(&mut store, "set_key_value").unwrap().typed::<(), ()>(&store).unwrap(); set_key_value.call(&mut store, ()).unwrap(); let get_key_value = instance.get_func(&mut store, "get_key_value").unwrap().typed::<(), ()>(&store).unwrap(); get_key_value.call(&mut store, ()).unwrap(); }
alexcrichton commented on issue #9017:
You'll want to to read over the documentation in the link I mentioned above, namely:
Next a wasmtime::Linker is configured with WASI imports by using the add_to_linker_* desired
which is this method
itachaaa commented on issue #9017:
Thanks!
alexcrichton closed issue #9017:
I know that there are some
wasi_snapshot_preview1::fd_write
related descriptions in the recent issue: 8521, 7697, and I addedadd_to_linker_sync
in my code. However, the type does not match and the compilation fails. Here are the details,I want to implement a small program that calls the cache interface in wasm.Running it directly throws an exception like this:
thread 'main' panicked at src/main.rs:62:67: called `Result::unwrap()` on an `Err` value: unknown import: `wasi_snapshot_preview1::fd_write` has not been defined note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
When I added
add_to_linker_sync
the compile Error:error[E0308]: mismatched types --> src/main.rs:62:39 | 62 | wasmtime_wasi::add_to_linker_sync(&mut linker).unwrap(); | --------------------------------- ^^^^^^^^^^^ expected `&mut Linker<_>`, found `&mut Linker<Arc<Mutex<KvStore>>>` | | | arguments to this function are incorrect | = note: expected mutable reference `&mut wasmtime::component::Linker<_>` found mutable reference `&mut wasmtime::Linker<Arc<Mutex<KvStore>>>`
wasm_runner:
use wasmtime::*; use kv_store::{create_kv_store, SharedKvStore}; fn main() { let mut config = Config::new(); Config::async_support(&mut config, false); config.wasm_backtrace_details(WasmBacktraceDetails::Enable); config.wasm_component_model(true); let engine = Engine::new(&config).unwrap(); let kv_store = create_kv_store(); let mut store = Store::new(&engine, kv_store.clone()); // Load the WebAssembly module // let caller_wasm = fs::read("../caller/target/wasm32-wasi/release/caller.wasm").unwrap(); let caller_module = Module::from_file(&engine, "../caller/target/wasm32-wasi/release/caller.wasm").unwrap(); // Create a new Linker to link WASI functions let mut linker = Linker::new(&engine); // Register the `get` function linker.func_wrap("env", "kv_get", move |mut caller: Caller<'_, SharedKvStore>, ptr: i32, len: i32, result_ptr: i32| -> i32 { let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); let data = memory.data(&caller); // Immutable access to memory to read key let key = &data[ptr as usize..(ptr + len) as usize]; let key_str = std::str::from_utf8(key).unwrap(); // Perform lookup in the shared KV store let value_opt = caller.data().lock().unwrap().get(key_str); // Mutable access to memory to write result let data_mut = memory.data_mut(&mut caller); if let Some(value) = value_opt { let value_bytes = value.as_bytes(); let result_slice = &mut data_mut[result_ptr as usize..(result_ptr as usize + value_bytes.len())]; result_slice.copy_from_slice(value_bytes); value_bytes.len() as i32 } else { -1 } }).unwrap(); // Register the `set` function linker.func_wrap("env", "kv_set", move |mut caller: Caller<'_, SharedKvStore>, key_ptr: i32, key_len: i32, value_ptr: i32, value_len: i32| { let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); let data = memory.data(&caller); // Immutable access to memory to read key and value let key = &data[key_ptr as usize..(key_ptr + key_len) as usize]; let value = &data[value_ptr as usize..(value_ptr + value_len) as usize]; let key_str = std::str::from_utf8(key).unwrap(); let value_str = std::str::from_utf8(value).unwrap(); // Perform write operation in the shared KV store caller.data().lock().unwrap().set(key_str, value_str); }) .unwrap(); // Instantiate the module // wasmtime_wasi::add_to_linker_sync(&mut linker).unwrap(); let instance = linker.instantiate(&mut store, &caller_module).unwrap(); // Call WebAssembly functions let set_key_value = instance.get_func(&mut store, "set_key_value").unwrap().typed::<(i32, i32), ()>(&store).unwrap(); set_key_value.call(&mut store, (0, 0)).unwrap(); let get_key_value = instance.get_func(&mut store, "get_key_value").unwrap().typed::<i32, i32>(&store).unwrap(); let result = get_key_value.call(&mut store, 0).unwrap(); println!("Got value from KV store: {}", result); }
[package] name = "wasm_runner" version = "0.1.0" edition = "2021" [dependencies] wasmtime = "23.0.1" wasmtime-wasi = "23.0.1" kv_store = { path = "../kv_store" }
caller:
extern "C" { pub fn kv_get(ptr: *const u8, len: usize, result_ptr: *mut u8) -> i32; pub fn kv_set(key_ptr: *const u8, key_len: usize, value_ptr: *const u8, value_len: usize); } #[no_mangle] pub unsafe fn set_key_value(key: &str, value: &str) { unsafe { kv_set(key.as_ptr(), key.len(), value.as_ptr(), value.len()); } } #[no_mangle] pub unsafe fn get_key_value(key: &str) -> Option<String> { let mut result = vec![0u8; 100]; // 假设结果长度不会超过100字节 let result_ptr = result.as_mut_ptr(); let len = unsafe { kv_get(key.as_ptr(), key.len(), result_ptr) }; if len >= 0 { Some(String::from_utf8(result[..len as usize].to_vec()).unwrap()) } else { None } }
[package] name = "caller" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"]
use std::collections::HashMap; use std::sync::{Arc, Mutex}; pub struct KvStore { map: HashMap<String, String>, } impl KvStore { pub fn new() -> Self { KvStore { map: HashMap::new(), } } pub fn get(&self, key: &str) -> Option<String> { self.map.get(key).cloned() } pub fn set(&mut self, key: &str, value: &str) { self.map.insert(key.to_string(), value.to_string()); } } pub type SharedKvStore = Arc<Mutex<KvStore>>; pub fn create_kv_store() -> SharedKvStore { Arc::new(Mutex::new(KvStore::new())) }
Last updated: Dec 23 2024 at 13:07 UTC