From d169966f76c739d184a294fe08446b3b787fff8f Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 25 Oct 2020 21:39:58 -0400 Subject: [PATCH] [bindings] Update eq/clone trait fns to take object, not this_arg When a trait is required to implement eq/clone (eg in the case of `SocketDescriptor`), the generated trait struct contains an eq/clone function which takes a `this_arg` pointer. Since the trait object can always be read to get the `this_arg` pointer, there is no loss of generality to pass the trait object itself, and it provides a bit more flexibility when the trait could be one of several implementations (which we use in the Java higher-level bindings). --- c-bindings-gen/src/main.rs | 21 +++++++++++++-------- lightning-c-bindings/demo.cpp | 4 ++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/c-bindings-gen/src/main.rs b/c-bindings-gen/src/main.rs index be3d36724..4193f6d36 100644 --- a/c-bindings-gen/src/main.rs +++ b/c-bindings-gen/src/main.rs @@ -226,7 +226,8 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty generated_fields.push("clone".to_owned()); }, ("std::cmp::Eq", _) => { - writeln!(w, "\tpub eq: extern \"C\" fn (this_arg: *const c_void, other_arg: *const c_void) -> bool,").unwrap(); + writeln!(w, "\tpub eq: extern \"C\" fn (this_arg: *const c_void, other_arg: &{}) -> bool,", trait_name).unwrap(); + writeln!(extra_headers, "typedef struct LDK{} LDK{};", trait_name, trait_name).unwrap(); generated_fields.push("eq".to_owned()); }, ("std::hash::Hash", _) => { @@ -251,21 +252,25 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty ("std::cmp::Eq", _) => { writeln!(w, "impl std::cmp::Eq for {} {{}}", trait_name).unwrap(); writeln!(w, "impl std::cmp::PartialEq for {} {{", trait_name).unwrap(); - writeln!(w, "\tfn eq(&self, o: &Self) -> bool {{ (self.eq)(self.this_arg, o.this_arg) }}\n}}").unwrap(); + writeln!(w, "\tfn eq(&self, o: &Self) -> bool {{ (self.eq)(self.this_arg, o) }}\n}}").unwrap(); }, ("std::hash::Hash", _) => { writeln!(w, "impl std::hash::Hash for {} {{", trait_name).unwrap(); writeln!(w, "\tfn hash(&self, hasher: &mut H) {{ hasher.write_u64((self.hash)(self.this_arg)) }}\n}}").unwrap(); }, ("Clone", _) => { - writeln!(w, "impl Clone for {} {{", trait_name).unwrap(); - writeln!(w, "\tfn clone(&self) -> Self {{").unwrap(); - writeln!(w, "\t\tSelf {{").unwrap(); - writeln!(w, "\t\tthis_arg: if let Some(f) = self.clone {{ (f)(self.this_arg) }} else {{ self.this_arg }},").unwrap(); + writeln!(w, "#[no_mangle]").unwrap(); + writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{", trait_name, trait_name, trait_name).unwrap(); + writeln!(w, "\t{} {{", trait_name).unwrap(); + writeln!(w, "\t\tthis_arg: if let Some(f) = orig.clone {{ (f)(orig.this_arg) }} else {{ orig.this_arg }},").unwrap(); for field in generated_fields.iter() { - writeln!(w, "\t\t\t{}: self.{}.clone(),", field, field).unwrap(); + writeln!(w, "\t\t{}: orig.{}.clone(),", field, field).unwrap(); } - writeln!(w, "\t\t}}\n\t}}\n}}").unwrap(); + writeln!(w, "\t}}\n}}").unwrap(); + writeln!(w, "impl Clone for {} {{", trait_name).unwrap(); + writeln!(w, "\tfn clone(&self) -> Self {{").unwrap(); + writeln!(w, "\t\t{}_clone(self)", trait_name).unwrap(); + writeln!(w, "\t}}\n}}").unwrap(); }, (s, i) => { if s != "util::events::MessageSendEventsProvider" { unimplemented!(); } diff --git a/lightning-c-bindings/demo.cpp b/lightning-c-bindings/demo.cpp index 36a11a783..84d7904f8 100644 --- a/lightning-c-bindings/demo.cpp +++ b/lightning-c-bindings/demo.cpp @@ -191,8 +191,8 @@ uintptr_t sock_send_data(void *this_arg, LDKu8slice data, bool resume_read) { void sock_disconnect_socket(void *this_arg) { close((int)((long)this_arg)); } -bool sock_eq(const void *this_arg, const void *other_arg) { - return this_arg == other_arg; +bool sock_eq(const void *this_arg, const LDKSocketDescriptor *other_arg) { + return this_arg == other_arg->this_arg; } uint64_t sock_hash(const void *this_arg) { return (uint64_t)this_arg; -- 2.39.5