diff options
| author | Teddy Wing | 2018-09-03 18:00:56 +0200 |
|---|---|---|
| committer | Teddy Wing | 2018-09-06 04:03:20 +0200 |
| commit | 84d29715900209b8ab4c600ad40ef99cdad03bd6 (patch) | |
| tree | 598fc93981cc3a1109ce1fa29136b264a093ed43 | |
| parent | 4b31eb9b8412e429949aca73ef475787910e4b0b (diff) | |
| download | dome-key-map-84d29715900209b8ab4c600ad40ef99cdad03bd6.tar.bz2 | |
Trying to fix pointer lifetime of mode `CKeyActionResult` (WIP)
Can't get this working. Tried a bunch of things. Decided to commit this
at a stopping point before messing any further. Sort of getting there,
with some things that seem like they're pointing in the right direction,
but it's not working out so far. Still getting a segfault. Actually,
with the `Box::into_raw` addition, the lifetime of the mode result
actually lasts for a single call (printf), and then gets freed
(weirdly).
Makefile:
* Add `-W` error flags to see if those would give me any extra
information about the pointer problems, but didn't get anything. The
fact that I didn't get errors indicated it was a problem on the Rust
side.
* Change `clean` dependency to `moder.c` so we don't rebuild if the C
file (and lib) hasn't changed.
c_run_key_action():
* Add some `println!`s and debug clutter
* Add a separate `let` binding for `run_key_action_for_mode()` because
that seemed to fix some weirdness in control flow when I was debugging
the code at one point in `lldb`. Not sure it this change still makes
sense to keep.
* Changed function/closure version of `in_mode` to `if`/`else` because
that may have made a difference in some dumb things I was
experimenting with at some point.
* Unsuccessful tries of `mem::forget()`, ultimately commented out.
* Return a `Box::into_raw` pointer to the `CKeyActionResult` instead of
the Rust pointer we were previously returning. This allows the value
to live beyond the function and beyond Rust's control into the calling
C code. This does, however, mean that the value leaks memory, and will
need to be freed manually in the calling C code.
run_key_action_for_mode():
* Wrap map handler in a check to verify `in_mode` is `None`. This
ensures that if we should be returning a `KeyActionResult` for a
mapping inside a mode, we don't run this code that's meant for
mappings outside a mode.
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | moder.c | 2 | ||||
| -rw-r--r-- | src/cocoa_bridge.rs | 100 |
3 files changed, 70 insertions, 36 deletions
@@ -8,8 +8,8 @@ $(LIB): $(SOURCE_FILES) includer: clean $(LIB) gcc -o $@ includer.c $(LIB) -moder: clean $(LIB) - gcc -o $@ $@.c $(LIB) +moder: moder.c $(LIB) + gcc -g -Wall -Wextra -Werror -o $@ $< $(LIB) .PHONY: clean clean: @@ -10,7 +10,7 @@ int main() { .length = SIZE }; const CKeyActionResult *mode = c_run_key_action(mode_trigger, NULL); - printf("%d\n", *mode->kind); + /* printf("%d\n", *mode->kind); */ HeadphoneButton buttons[] = {HeadphoneButton_Down}; Trigger trigger = { diff --git a/src/cocoa_bridge.rs b/src/cocoa_bridge.rs index 15cee95..8581b46 100644 --- a/src/cocoa_bridge.rs +++ b/src/cocoa_bridge.rs @@ -1,4 +1,5 @@ use std::ffi::{CStr, CString}; +use std::mem; use std::ptr; use std::slice; @@ -42,6 +43,7 @@ struct renameMeMapGroup { // Somehow: switch mode inside Rust #[repr(C)] +#[derive(Debug)] pub struct Trigger { pub buttons: *const HeadphoneButton, pub length: size_t, @@ -83,6 +85,7 @@ impl<'a> KeyActionResult<'a> { } #[repr(C)] +#[derive(Debug)] pub struct CKeyActionResult { pub action: *const c_char, pub kind: *const ActionKind, @@ -104,6 +107,7 @@ pub extern "C" fn c_run_key_action( if mode.is_null() { None } else { + println!("{:?}", *mode); assert!(!(*mode).buttons.is_null()); Some( @@ -111,30 +115,52 @@ pub extern "C" fn c_run_key_action( ) } }; + println!("{:?}", mode); - let result = match run_key_action_for_mode(trigger, mode) { + let result = run_key_action_for_mode(trigger, mode); + let result = match result { Some(k) => { let action = k.action.map_or_else( || ptr::null(), |a| a.into_raw(), ); - let in_mode = k.in_mode.map_or_else( - || ptr::null(), - |m| { - let trigger = Trigger { - buttons: m.as_ptr(), - length: m.len(), - }; - - &trigger - }, - ); - - CKeyActionResult { + // let in_mode = k.in_mode.map_or_else( + // || ptr::null(), + // |m| { + // let trigger = Trigger { + // buttons: m.as_ptr(), + // length: m.len(), + // }; + // mem::forget(m); + // + // &trigger + // }, + // ); + let trigger; + let in_mode = if let Some(m) = k.in_mode { + trigger = Trigger { + buttons: m.as_ptr(), + length: m.len(), + }; + + &trigger + } else { + ptr::null() + }; + // mem::forget(k.in_mode); + // mem::forget(in_mode); + // println!("IN MODE: {:?}", &in_mode); + // let in_mode2 = Box::new(k.in_mode); + // let in_mode_ptr = Box::into_raw(in_mode2); + + let result = CKeyActionResult { action: action, // memory leak, must be freed from Rust kind: &k.kind, in_mode: in_mode, - } + }; + println!("{:?}", result); + // mem::forget(result); + result }, None => { CKeyActionResult { @@ -144,8 +170,13 @@ pub extern "C" fn c_run_key_action( } } }; + // println!("hey result: {:?}", result); + // mem::forget(result); + let r = Box::new(result); + let r2 = Box::into_raw(r); - &result as *const CKeyActionResult + // &result as *const CKeyActionResult + r2 as *const CKeyActionResult } #[no_mangle] @@ -189,23 +220,26 @@ mode <play><up> { } } - if let Some(map) = map { - return match map.kind { - MapKind::Map => { - Some( - KeyActionResult::new(ActionKind::Map) - .with_action(&map.action) - ) - }, - MapKind::Command => { - Some( - KeyActionResult::new(ActionKind::Command) - ) - }, - // MapKind::Mode => { - // TODO: Maybe make a new type just for KeyActionResult that - // combines regular MapKinds and Mode - // }, + // TODO: make sure this doesn't run when in_mode + if in_mode.is_none() { + if let Some(map) = map { + return match map.kind { + MapKind::Map => { + Some( + KeyActionResult::new(ActionKind::Map) + .with_action(&map.action) + ) + }, + MapKind::Command => { + Some( + KeyActionResult::new(ActionKind::Command) + ) + }, + // MapKind::Mode => { + // TODO: Maybe make a new type just for KeyActionResult that + // combines regular MapKinds and Mode + // }, + } } } |
