From 43ca0569c6689659930dbd2e7af09383f5a25bbd Mon Sep 17 00:00:00 2001 From: Dannii Willis Date: Tue, 5 Mar 2024 11:28:40 +1000 Subject: [PATCH] NOT WORKING: in wasm the DispatchRocks aren't being preserved for retained arrays --- remglk/src/glkapi/mod.rs | 24 ++++++++++++--- remglk/src/glkapi/objects.rs | 2 +- remglk_capi/src/glk/support.c | 13 +++++++- remglk_capi/src/systems/emglken.rs | 36 +++++++++++----------- remglk_capi/src/systems/library_emglken.js | 7 +++++ 5 files changed, 57 insertions(+), 25 deletions(-) diff --git a/remglk/src/glkapi/mod.rs b/remglk/src/glkapi/mod.rs index a75accb..772e827 100644 --- a/remglk/src/glkapi/mod.rs +++ b/remglk/src/glkapi/mod.rs @@ -1566,12 +1566,20 @@ where S: Default + GlkSystem { match buf { GlkBuffer::U8(buf) => { let mut disprock: MaybeUninit = MaybeUninit::uninit(); - (self.retain_array_callbacks_u8.as_ref().unwrap().retain)(buf.as_ptr(), buf.len() as u32, "&+#!Cn".as_ptr(), disprock.as_mut_ptr()); - unsafe {disprock.assume_init()} + (self.retain_array_callbacks_u8.as_ref().unwrap().retain)(buf.as_ptr(), buf.len() as u32, b"&+#!Cn\0".as_ptr(), disprock.as_mut_ptr()); + let disprock_ptr = disprock.as_mut_ptr(); + let disprock = unsafe {disprock.assume_init()}; + println!("retain_array {:?} {:?} {}", buf.as_ptr(), disprock_ptr, unsafe { std::mem::transmute::(disprock) }); + extern "C" { + fn print_disprock(disprock: DispatchRock); + } + unsafe {print_disprock(disprock)}; + disprock }, GlkBuffer::U32(buf) => { let mut disprock: MaybeUninit = MaybeUninit::uninit(); - (self.retain_array_callbacks_u32.as_ref().unwrap().retain)(buf.as_ptr(), buf.len() as u32, "&+#!Iu".as_ptr(), disprock.as_mut_ptr()); + (self.retain_array_callbacks_u32.as_ref().unwrap().retain)(buf.as_ptr(), buf.len() as u32, b"&+#!Iu\0".as_ptr(), disprock.as_mut_ptr()); + println!("retain_array {:?} {}", buf.as_ptr(), unsafe { std::mem::transmute::(disprock.assume_init()) }); unsafe {disprock.assume_init()} }, } @@ -1580,8 +1588,14 @@ where S: Default + GlkSystem { pub fn unretain_array(&self, buf: GlkOwnedBuffer, disprock: DispatchRock) { let len = buf.len() as u32; match buf { - GlkOwnedBuffer::U8(buf) => (self.retain_array_callbacks_u8.as_ref().unwrap().unretain)(Box::leak(buf).as_ptr(), len, "&+#!Cn".as_ptr(), disprock), - GlkOwnedBuffer::U32(buf) => (self.retain_array_callbacks_u32.as_ref().unwrap().unretain)(Box::leak(buf).as_ptr(), len, "&+#!Iu".as_ptr(), disprock), + GlkOwnedBuffer::U8(buf) => { + println!("unretain_array {:?} {}", buf.as_ptr(), unsafe { std::mem::transmute::(disprock) }); + (self.retain_array_callbacks_u8.as_ref().unwrap().unretain)(Box::leak(buf).as_ptr(), len, b"&+#!Cn\0".as_ptr(), disprock) + }, + GlkOwnedBuffer::U32(buf) => { + println!("unretain_array {:?} {}", buf.as_ptr(), unsafe { std::mem::transmute::(disprock) }); + (self.retain_array_callbacks_u32.as_ref().unwrap().unretain)(Box::leak(buf).as_ptr(), len, b"&+#!Iu\0".as_ptr(), disprock) + }, }; } } diff --git a/remglk/src/glkapi/objects.rs b/remglk/src/glkapi/objects.rs index 2b5a16a..7e6e534 100644 --- a/remglk/src/glkapi/objects.rs +++ b/remglk/src/glkapi/objects.rs @@ -129,7 +129,7 @@ where T: Default + GlkObjectClass, GlkObject: Default + Eq { obj.id = self.counter; obj.rock = rock; self.counter += 1; - if let Some(_) = self.register_cb { + if self.register_cb.is_some() { obj.disprock = Some(self.register_callback(obj_ptr, self.object_class)); } match self.first.as_ref() { diff --git a/remglk_capi/src/glk/support.c b/remglk_capi/src/glk/support.c index 2d82206..5bbcad4 100644 --- a/remglk_capi/src/glk/support.c +++ b/remglk_capi/src/glk/support.c @@ -14,6 +14,7 @@ MIT licenced #include "support.h" gidispatch_rock_t (*gli_register_arr)(void *array, glui32 len, char *typecode) = NULL; +void (*gli_unregister_arr)(void *array, glui32 len, char *typecode, gidispatch_rock_t objrock) = NULL; gidispatch_rock_t (*gli_register_obj)(void *obj, glui32 objclass) = NULL; gidispatch_rock_t gidispatch_get_objrock(void *obj, glui32 objclass) { @@ -33,15 +34,24 @@ gidispatch_rock_t gidispatch_get_objrock(void *obj, glui32 objclass) { } } +#include // Because of a WASM ABI issue, we call the VM's registry functions indirectly void gidispatch_call_array_register(void *array, glui32 len, char *typecode, gidispatch_rock_t *rock_ptr) { gidispatch_rock_t rock = gli_register_arr(array, len, typecode); + printf("gidispatch_call_array_register %p %s %d %p\n", array, typecode, rock, rock_ptr); *rock_ptr = rock; } +void gidispatch_call_array_unregister(void *array, glui32 len, char *typecode, gidispatch_rock_t objrock) { + printf("gidispatch_call_array_unregister %p %s %d\n", array, typecode, objrock); + gli_unregister_arr(array, len, typecode, objrock); +} void gidispatch_call_object_register(void *obj, glui32 objclass, gidispatch_rock_t *rock_ptr) { gidispatch_rock_t rock = gli_register_obj(obj, objclass); *rock_ptr = rock; } +void print_disprock(gidispatch_rock_t objrock) { + printf("print_disprock %d\n", objrock); +} void gidispatch_set_object_registry( gidispatch_rock_t (*regi)(void *obj, glui32 objclass), @@ -55,7 +65,8 @@ void gidispatch_set_retained_registry( void (*unregi)(void *array, glui32 len, char *typecode, gidispatch_rock_t objrock)) { gli_register_arr = regi; - gidispatch_set_retained_registry_rs(gidispatch_call_array_register, unregi); + gli_unregister_arr = unregi; + gidispatch_set_retained_registry_rs(gidispatch_call_array_register, gidispatch_call_array_unregister); } glkunix_argumentlist_t *glkunix_arguments_addr(void) { diff --git a/remglk_capi/src/systems/emglken.rs b/remglk_capi/src/systems/emglken.rs index 20c019e..7437f0b 100644 --- a/remglk_capi/src/systems/emglken.rs +++ b/remglk_capi/src/systems/emglken.rs @@ -10,7 +10,7 @@ https://github.com/curiousdannii/remglk-rs */ use std::collections::HashMap; -use std::ptr; +use std::mem::MaybeUninit; use std::slice; use super::*; @@ -19,8 +19,9 @@ use glkapi::protocol::{Event, SystemFileRef, Update}; extern "C" { fn emglken_fileref_exists(filename_ptr: *const u8, filename_len: usize) -> bool; - fn emglken_fileref_read(filename_ptr: *const u8, filename_len: usize, buffer: &mut EmglkenBuffer) -> bool; - fn emglken_get_glkote_event(buffer: &mut EmglkenBuffer); + fn emglken_fileref_read(filename_ptr: *const u8, filename_len: usize, buffer: *mut EmglkenBuffer) -> bool; + fn emglken_get_glkote_event(buffer: *mut EmglkenBuffer); + fn emglken_send_glkote_update(update_ptr: *const u8, update_len: usize); } #[repr(C)] @@ -67,13 +68,10 @@ impl GlkSystem for EmglkenSystem { Some(buf.clone()) } else { - let mut buf = EmglkenBuffer { - ptr: ptr::null_mut(), - len: 0, - }; - let result = unsafe {emglken_fileref_read(fileref.filename.as_ptr(), fileref.filename.len(), &mut buf)}; + let mut buf: MaybeUninit = MaybeUninit::uninit(); + let result = unsafe {emglken_fileref_read(fileref.filename.as_ptr(), fileref.filename.len(), buf.as_mut_ptr())}; if result { - return Some(buffer_to_boxed_slice(&buf)); + return Some(buffer_to_boxed_slice(&unsafe {buf.assume_init()})); } None } @@ -88,22 +86,24 @@ impl GlkSystem for EmglkenSystem { } fn flush_writeable_files(&mut self) { - unimplemented!() + for (_filename, _buf) in self.cache.drain() { + unimplemented!() + } + self.cache.shrink_to(4); } fn get_glkote_event(&mut self) -> Option { - let mut buf = EmglkenBuffer { - ptr: ptr::null_mut(), - len: 0, - }; - unsafe {emglken_get_glkote_event(&mut buf)}; - let data = buffer_to_boxed_slice(&buf); + let mut buf: MaybeUninit = MaybeUninit::uninit(); + unsafe {emglken_get_glkote_event(buf.as_mut_ptr())}; + let data = buffer_to_boxed_slice(&unsafe {buf.assume_init()}); let event: Event = serde_json::from_slice(&data).unwrap(); return Some(event); } - fn send_glkote_update(&mut self, _update: Update) { - unimplemented!() + fn send_glkote_update(&mut self, update: Update) { + // Send the update + let output = serde_json::to_string(&update).unwrap(); + unsafe {emglken_send_glkote_update(output.as_ptr(), output.len())}; } } diff --git a/remglk_capi/src/systems/library_emglken.js b/remglk_capi/src/systems/library_emglken.js index 3d153b7..7fce239 100644 --- a/remglk_capi/src/systems/library_emglken.js +++ b/remglk_capi/src/systems/library_emglken.js @@ -37,6 +37,13 @@ addToLibrary({ }) }, + emglken_send_glkote_update(update_ptr, update_len) { + const update = UTF8ToString(update_ptr, update_len) + const obj = JSON.parse(update) + // TODO: Store the usage of a fileref prompt request? + GlkOte.update(obj) + }, + $writeBuffer(buffer, data) { const ptr = _malloc(data.length) HEAP8.set(data, ptr)