Lohann opened issue #9579:
Thanks for filing a feature request! Please fill out the TODOs below.
Feature
Hello, I need to access the imported memory inside a functions, then I realized the Caller only show exports, not imports, so I had a lot of trouble to get Wasmtime store working with MaybeUnit, this simple solution segfaults:
pub struct State { pub memory: Memory, } let state = MaybeUninit::<State>::uninit(); let mut store = Store::new(engine, state); let memory_type = MemoryType::new(16, None); store.data_mut().memory.write(Memory::new(&mut store, memory_type)?); let store = unsafe { std::mem::transmute::<Store<MaybeUninit<State>>, Store<State>>(store) }; // segfaults below let instance = Instance::new(&mut store, &module, &imports)?;
Then I realized the issue is that there's no way for me transmute only the State, I need to transmute the Store which is not recommended, once rust doesn't guarantee the same memory layout:
assert_eq!(size_of::<Option<bool>>(), 1); assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
Actually I haven't find any way to use MaybeUnit that doesn't look hacky, and I want to avoid the usage of Option and unwraps in the code, once it bloats the binary with panic data.
Alternatives
- Make the imported memory easily available inside Functions, ex: expose it in the Caller.
- Use
#[repr(C)]
onStore
, so we can safely transmute it.
Lohann edited issue #9579:
Thanks for filing a feature request! Please fill out the TODOs below.
Feature
Hello, I need to access the imported memory inside a functions, then I realized the Caller only show exports, not imports, so I had a lot of trouble to get Wasmtime store working with MaybeUnit, this simple solution segfaults:
pub struct State { pub memory: Memory, } let state = MaybeUninit::<State>::uninit(); let mut store = Store::new(engine, state); let memory_type = MemoryType::new(16, None); store.data_mut().memory.write(Memory::new(&mut store, memory_type)?); let store = unsafe { std::mem::transmute::<Store<MaybeUninit<State>>, Store<State>>(store) }; // ... let imports = [memory.into()]; // segfaults below let instance = Instance::new(&mut store, &module, &imports)?;
Then I realized the issue is that there's no way for me transmute only the State, I need to transmute the Store which is not recommended, once rust doesn't guarantee the same memory layout:
assert_eq!(size_of::<Option<bool>>(), 1); assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
Actually I haven't find any way to use MaybeUnit that doesn't look hacky, and I want to avoid the usage of Option and unwraps in the code, once it bloats the binary with panic data.
Alternatives
- Make the imported memory easily available inside Functions, ex: expose it in the Caller.
- Use
#[repr(C)]
onStore
, so we can safely transmute it.
alexcrichton commented on issue #9579:
Where possible I'd recommend avoiding
unsafe
. If things are segfaulting it's probably due to that, so for example you could storeOption<Memory>
instead of usingMaybeUninit
and then there's no need fortransmute
and this probably won't segfault.Otherwise though is there a problem with storing the memory in
State
?
Lohann commented on issue #9579:
Otherwise though is there a problem with storing the memory in State?
There's no problem, is just there's no examples of that, and is not ergonomic as using exported memory, rust encourages the use of Typestate Pattern, where the state of an object guarantees it is valid. In this case I want to guarantee the memory ALWAYS exists, that's why I don't want to use Option.
One example is the NonZeroU32 by knowing the number is never zero, the rust compiler can do some neat optimizations:assert_eq!(size_of::<u32>(), 4); assert_eq!(size_of::<Option<u32>>(), 8); assert_eq!(size_of::<Option<NonZeroU32>>(), 4);
In my case I want to guarantee the memory always exists, I don't want to handle the
Option::None
everywhere, neither useunwrap()
everywhere, that's ok if there's no other option, but I think this is something that should be supported somehow by wasmtime, once the Store owns the memory, makes sense I be able to store it together with the store.
Lohann edited a comment on issue #9579:
Otherwise though is there a problem with storing the memory in State?
There's no problem, but rust encourages the use of Typestate Pattern, where the state of an object guarantees it is valid. In this case I want to guarantee the memory ALWAYS exists, that's why I don't want to use Option.
One example is the NonZeroU32 by knowing the number is never zero, the rust compiler can do some neat optimizations:assert_eq!(size_of::<u32>(), 4); assert_eq!(size_of::<Option<u32>>(), 8); assert_eq!(size_of::<Option<NonZeroU32>>(), 4);
In my case I want to guarantee the memory always exists, I don't want to handle the
Option::None
everywhere, neither useunwrap()
everywhere, that's ok if there's no other option, but I think this is something that should be supported somehow by wasmtime, once the Store owns the memory, makes sense I be able to store it together with the store.
alexcrichton commented on issue #9579:
One thing you could perhaps do is to create a dummy
Memory
with a throwawayStore
which is placed within futureStore
s as they're created. That would then be overwritten to the "real" memory once the store is created. That way you can store justMemory
without having to deal withOption
and you won't have to deal with any unsafety either.
Last updated: Dec 23 2024 at 12:05 UTC