Redo tuple mapping to be explicit and not generic
authorMatt Corallo <git@bluematt.me>
Mon, 27 Sep 2021 00:05:18 +0000 (00:05 +0000)
committerMatt Corallo <git@bluematt.me>
Mon, 27 Sep 2021 05:22:38 +0000 (05:22 +0000)
This was suggested by Galder as more Java-y, but also fixes
a number of memory leaks by avoiding the complexity of
always holding references and letting the common code do
more work.

gen_type_mapping.py
genbindings.py
java_strings.py
typescript_strings.py

index 5902fb262dc4e7e90748707cd7f2695bedb28166..fc0e6cddc65d18f350ba0d625521eb6e11d2bc73 100644 (file)
@@ -268,12 +268,15 @@ class TypeMappingGenerator:
                     opaque_ret_conv_suf = opaque_ret_conv_suf + "\t" + ty_info.var_name + "_ref |= 1;\n"
                     opaque_ret_conv_suf = opaque_ret_conv_suf + "}"
 
+                to_hu_conv_sfx = ""
+                if not ty_info.is_ptr or holds_ref:
+                    to_hu_conv_sfx = "\n" + ty_info.var_name + "_hu_conv.ptrs_to.add(this);"
                 if ty_info.is_ptr:
                     return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name,
                         arg_conv = opaque_arg_conv, arg_conv_name = "&" + ty_info.var_name + "_conv", arg_conv_cleanup = None,
                         ret_conv = (ty_info.rust_obj + " " + ty_info.var_name + "_var = *", opaque_ret_conv_suf),
                         ret_conv_name = ty_info.var_name + "_ref",
-                        to_hu_conv = self.consts.to_hu_conv_templates['ptr'].replace('{human_type}', ty_info.java_hu_ty).replace('{var_name}', ty_info.var_name),
+                        to_hu_conv = self.consts.to_hu_conv_templates['ptr'].replace('{human_type}', ty_info.java_hu_ty).replace('{var_name}', ty_info.var_name) + to_hu_conv_sfx,
                         to_hu_conv_name = ty_info.var_name + "_hu_conv",
                         from_hu_conv = from_hu_conv)
                 else:
@@ -281,7 +284,7 @@ class TypeMappingGenerator:
                         arg_conv = opaque_arg_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None,
                         ret_conv = (ty_info.rust_obj + " " + ty_info.var_name + "_var = ", opaque_ret_conv_suf),
                         ret_conv_name = ty_info.var_name + "_ref",
-                        to_hu_conv = self.consts.to_hu_conv_templates['default'].replace('{human_type}', ty_info.java_hu_ty).replace('{var_name}', ty_info.var_name) + "\n" + ty_info.var_name + "_hu_conv.ptrs_to.add(this);",
+                        to_hu_conv = self.consts.to_hu_conv_templates['default'].replace('{human_type}', ty_info.java_hu_ty).replace('{var_name}', ty_info.var_name) + to_hu_conv_sfx,
                         to_hu_conv_name = ty_info.var_name + "_hu_conv",
                         from_hu_conv = from_hu_conv)
 
@@ -375,60 +378,27 @@ class TypeMappingGenerator:
                         to_hu_conv = ty_info.java_hu_ty + " " + ty_info.var_name + "_hu_conv = " + ty_info.java_hu_ty + ".constr_from_ptr(" + ty_info.var_name + ");",
                         to_hu_conv_name = ty_info.var_name + "_hu_conv", from_hu_conv = (ty_info.var_name + " != null ? " + ty_info.var_name + ".ptr : 0", ""))
                 if ty_info.rust_obj in self.tuple_types:
-                    from_hu_conv_sfx = ""
-                    from_hu_conv = "bindings." + self.tuple_types[ty_info.rust_obj][1].replace("LDK", "") + "_new("
-                    to_hu_conv_pfx = ""
-                    to_hu_conv_sfx = ty_info.java_hu_ty + " " + ty_info.var_name + "_conv = new " + ty_info.java_hu_ty + "("
-                    to_hu_conv_refs = ""
-                    for idx, conv in enumerate(self.tuple_types[ty_info.rust_obj][0]):
-                        if idx != 0:
-                            to_hu_conv_sfx = to_hu_conv_sfx + ", "
-                            from_hu_conv = from_hu_conv + ", "
-                        conv.var_name = ty_info.var_name + "_" + chr(idx + ord("a"))
-                        conv_map = self.map_type_with_info(conv, False, None, is_free, holds_ref)
-                        to_hu_conv_pfx = to_hu_conv_pfx + conv.java_ty + " " + ty_info.var_name + "_" + chr(idx + ord("a")) + " = "
-                        if not conv.is_native_primitive and (conv_map.rust_obj.replace("LDK", "") + "_clone") in self.clone_fns and conv_map.rust_obj == "LDKTxOut":
-                            to_hu_conv_pfx = to_hu_conv_pfx + "bindings." + conv_map.rust_obj.replace("LDK", "") + "_clone("
-                        to_hu_conv_pfx = to_hu_conv_pfx + "bindings." + self.tuple_types[ty_info.rust_obj][1] + "_get_" + chr(idx + ord("a")) + "(" + ty_info.var_name + ")"
-                        if not conv.is_native_primitive and (conv_map.rust_obj.replace("LDK", "") + "_clone") in self.clone_fns and conv_map.rust_obj == "LDKTxOut": # XXX
-                            to_hu_conv_pfx = to_hu_conv_pfx + ")"
-                        to_hu_conv_pfx = to_hu_conv_pfx + ";\n"
-                        if conv_map.to_hu_conv is not None:
-                            to_hu_conv_pfx = to_hu_conv_pfx + conv_map.to_hu_conv + ";\n"
-                            to_hu_conv_sfx = to_hu_conv_sfx + conv_map.to_hu_conv_name
-                            if to_hu_conv_refs is not None:
-                                if conv_map.c_ty.endswith("Array"):
-                                    to_hu_conv_refs = None
-                                else:
-                                    to_hu_conv_refs = to_hu_conv_refs + "\n" + conv_map.to_hu_conv_name + ".ptrs_to.add(" + ty_info.var_name + "_conv);"
-                        else:
-                            to_hu_conv_sfx = to_hu_conv_sfx + ty_info.var_name + "_" + chr(idx + ord("a"))
-                        if conv_map.from_hu_conv is not None:
-                            from_hu_conv = from_hu_conv + conv_map.from_hu_conv[0].replace(ty_info.var_name + "_" + chr(idx + ord("a")), ty_info.var_name + "." + chr(idx + ord("a")))
-                            if conv_map.from_hu_conv[1] != "":
-                                from_hu_conv_sfx = from_hu_conv_sfx + conv_map.from_hu_conv[1].replace(conv.var_name, ty_info.var_name + "." + chr(idx + ord("a")))
-                                if idx != len(self.tuple_types[ty_info.rust_obj][0]) - 1:
-                                    from_hu_conv_sfx += "; "
+                    ret_conv_name = "((uint64_t)" + ty_info.var_name + "_conv)"
+                    if holds_ref:
+                        # If we're trying to return a ref, we have to clone.
+                        # We just blindly assume its implemented and let the compiler fail if its not.
+                        ret_conv = (ty_info.rust_obj + "* " + ty_info.var_name + "_conv = MALLOC(sizeof(" + ty_info.rust_obj + "), \"" + ty_info.rust_obj + "\");\n*" + ty_info.var_name + "_conv = ", ";")
+                        if (ty_info.rust_obj.replace("LDK", "") + "_clone") not in self.clone_fns:
+                            ret_conv = (ret_conv[0], ret_conv[1] + "\n// Warning: we really need to clone here, but no clone is available for " + ty_info.rust_obj)
+                            ret_conv_name += " | 1"
                         else:
-                            from_hu_conv = from_hu_conv + ty_info.var_name + "." + chr(idx + ord("a"))
-
-                    if to_hu_conv_refs is None:
-                        to_hu_conv = to_hu_conv_pfx + to_hu_conv_sfx + ");\n// Warning: We may not free the C tuple object!"
+                            ret_conv = (ret_conv[0], ret_conv[1] + "\n*" + ty_info.var_name + "_conv = " + ty_info.rust_obj.replace("LDK", "") + "_clone(" + ty_info.var_name + "_conv);")
                     else:
-                        to_hu_conv = to_hu_conv_pfx + to_hu_conv_sfx + ", () -> {\n"
-                        to_hu_conv = to_hu_conv + "\tbindings." + ty_info.rust_obj.replace("LDK", "") + "_free(" + ty_info.var_name + ");\n"
-                        to_hu_conv = to_hu_conv + "});" + to_hu_conv_refs
-                    if not ty_info.is_ptr and not holds_ref:
-                        ret_conv = (ty_info.rust_obj + "* " + ty_info.var_name + "_ref = MALLOC(sizeof(" + ty_info.rust_obj + "), \"" + ty_info.rust_obj + "\");\n*" + ty_info.var_name + "_ref = ", ";")
-                        return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name,
-                            arg_conv = base_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None,
-                            ret_conv = ret_conv,
-                            ret_conv_name = "(uint64_t)" + ty_info.var_name + "_ref",
-                            to_hu_conv = to_hu_conv, to_hu_conv_name = ty_info.var_name + "_conv", from_hu_conv = (from_hu_conv + ")", from_hu_conv_sfx))
+                        ret_conv = (ty_info.rust_obj + "* " + ty_info.var_name + "_conv = MALLOC(sizeof(" + ty_info.rust_obj + "), \"" + ty_info.rust_obj + "\");\n*" + ty_info.var_name + "_conv = ", ";")
+                    if not ty_info.is_ptr or holds_ref:
+                        to_hu_conv_sfx = "\n" + ty_info.var_name + "_hu_conv.ptrs_to.add(this);"
+                    else:
+                        to_hu_conv_sfx = ""
                     return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name,
                         arg_conv = base_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None,
-                        ret_conv = ("uint64_t " + ty_info.var_name + "_ref = (uint64_t)(&", ") | 1;"), ret_conv_name = ty_info.var_name + "_ref",
-                        to_hu_conv = to_hu_conv, to_hu_conv_name = ty_info.var_name + "_conv", from_hu_conv = (from_hu_conv + ")", from_hu_conv_sfx))
+                        ret_conv = ret_conv, ret_conv_name = ret_conv_name,
+                        to_hu_conv = ty_info.java_hu_ty + " " + ty_info.var_name + "_hu_conv = new " + ty_info.java_hu_ty + "(null, " + ty_info.var_name + ");" + to_hu_conv_sfx,
+                        to_hu_conv_name = ty_info.var_name + "_hu_conv", from_hu_conv = (ty_info.var_name + " != null ? " + ty_info.var_name + ".ptr : 0", ""))
 
                 # The manually-defined types - TxOut and u5
                 if ty_info.rust_obj == "LDKu5":
index 3733d540bc06f95e65e2221a9b458e83be29a862..1aa2c8ee3729b50f06c154cf4430c7e23779cc77 100755 (executable)
@@ -100,7 +100,7 @@ trait_structs = {}
 result_types = set()
 tuple_types = {}
 
-var_is_arr_regex = re.compile("\(\*([A-za-z0-9_]*)\)\[([a-z0-9]*)\]")
+var_is_arr_regex = re.compile("\(\* ?([A-za-z0-9_]*)\)\[([a-z0-9]*)\]")
 var_ty_regex = re.compile("([A-za-z_0-9]*)(.*)")
 java_c_types_none_allowed = True # Unset when we do the real pass that populates the above sets
 def java_c_types(fn_arg, ret_arr_len):
@@ -304,54 +304,15 @@ def java_c_types(fn_arg, ret_arr_len):
             fn_ty_arg = "Lorg/ldk/enums/" + java_ty + ";"
             fn_arg = ma.group(2).strip()
             rust_obj = ma.group(1).strip()
-        elif ma.group(1).strip().startswith("LDKC2Tuple"):
-            c_ty = consts.ptr_c_ty
-            java_ty = consts.ptr_native_ty
-            java_hu_ty = "TwoTuple<"
-            if not ma.group(1).strip() in tuple_types:
-                assert java_c_types_none_allowed
-                return None
-            for idx, ty_info in enumerate(tuple_types[ma.group(1).strip()][0]):
-                if idx != 0:
-                    java_hu_ty = java_hu_ty + ", "
-                if ty_info.is_native_primitive:
-                    if ty_info.java_hu_ty == "int":
-                        java_hu_ty = java_hu_ty + "Integer" # Java concrete integer type is Integer, not Int
-                    else:
-                        java_hu_ty = java_hu_ty + ty_info.java_hu_ty.title() # If we're a primitive, capitalize the first letter
-                else:
-                    java_hu_ty = java_hu_ty + ty_info.java_hu_ty
-            java_hu_ty = java_hu_ty + ">"
-            fn_ty_arg = "J"
-            fn_arg = ma.group(2).strip()
-            rust_obj = ma.group(1).strip()
-            take_by_ptr = True
-        elif ma.group(1).strip().startswith("LDKC3Tuple"):
-            c_ty = consts.ptr_c_ty
-            java_ty = consts.ptr_native_ty
-            java_hu_ty = "ThreeTuple<"
-            if not ma.group(1).strip() in tuple_types:
-                assert java_c_types_none_allowed
-                return None
-            for idx, ty_info in enumerate(tuple_types[ma.group(1).strip()][0]):
-                if idx != 0:
-                    java_hu_ty = java_hu_ty + ", "
-                if ty_info.is_native_primitive:
-                    if ty_info.java_hu_ty == "int":
-                        java_hu_ty = java_hu_ty + "Integer" # Java concrete integer type is Integer, not Int
-                    else:
-                        java_hu_ty = java_hu_ty + ty_info.java_hu_ty.title() # If we're a primitive, capitalize the first letter
-                else:
-                    java_hu_ty = java_hu_ty + ty_info.java_hu_ty
-            java_hu_ty = java_hu_ty + ">"
-            fn_ty_arg = "J"
-            fn_arg = ma.group(2).strip()
-            rust_obj = ma.group(1).strip()
-            take_by_ptr = True
         else:
             c_ty = consts.ptr_c_ty
             java_ty = consts.ptr_native_ty
-            java_hu_ty = ma.group(1).strip().replace("LDKCOption", "Option").replace("LDKCResult", "Result").replace("LDK", "")
+            java_hu_ty = ma.group(1).strip()
+            java_hu_ty = java_hu_ty.replace("LDKCOption", "Option")
+            java_hu_ty = java_hu_ty.replace("LDKCResult", "Result")
+            java_hu_ty = java_hu_ty.replace("LDKC2Tuple", "TwoTuple")
+            java_hu_ty = java_hu_ty.replace("LDKC3Tuple", "ThreeTuple")
+            java_hu_ty = java_hu_ty.replace("LDK", "")
             fn_ty_arg = "J"
             fn_arg = ma.group(2).strip()
             rust_obj = ma.group(1).strip()
@@ -427,19 +388,29 @@ with open(f"{sys.argv[3]}/structs/UtilMethods{consts.file_ext}", "a") as util:
 with open(sys.argv[1]) as in_h, open(f"{sys.argv[2]}/bindings{consts.file_ext}", "w") as out_java:
     # Map a top-level function
     def map_fn(line, re_match, ret_arr_len, c_call_string, doc_comment):
+        map_fn_with_ref_option(line, re_match, ret_arr_len, c_call_string, doc_comment, False)
+    def map_fn_with_ref_option(line, re_match, ret_arr_len, c_call_string, doc_comment, force_holds_ref):
         method_return_type = re_match.group(1)
         method_name = re_match.group(2)
-        orig_method_name = str(method_name)
         method_comma_separated_arguments = re_match.group(3)
         method_arguments = method_comma_separated_arguments.split(',')
 
         is_free = method_name.endswith("_free")
         if method_name.startswith("COption") or method_name.startswith("CResult"):
             struct_meth = method_name.rsplit("Z", 1)[0][1:] + "Z"
+            expected_struct = "LDKC" + struct_meth
+            struct_meth_name = method_name[len(struct_meth) + 1:].strip("_")
+        elif method_name.startswith("C2Tuple"):
+            tuple_name = method_name.rsplit("Z", 1)[0][2:] + "Z"
+            struct_meth = "Two" + tuple_name
+            expected_struct = "LDKC2" + tuple_name
+            struct_meth_name = method_name[len(tuple_name) + 2:].strip("_")
         else:
             struct_meth = method_name.split("_")[0]
+            expected_struct = "LDK" + struct_meth
+            struct_meth_name = method_name[len(struct_meth) + 1 if len(struct_meth) != 0 else 0:].strip("_")
 
-        return_type_info = type_mapping_generator.map_type(method_return_type.strip() + " ret", True, ret_arr_len, False, False)
+        return_type_info = type_mapping_generator.map_type(method_return_type.strip() + " ret", True, ret_arr_len, False, force_holds_ref)
 
         (params_nullable, ret_nullable) = doc_to_params_ret_nullable(doc_comment)
         if ret_nullable:
@@ -491,12 +462,13 @@ with open(sys.argv[1]) as in_h, open(f"{sys.argv[2]}/bindings{consts.file_ext}",
             argument_types.append(argument_conversion_info)
         if not takes_self and return_type_info.java_hu_ty != struct_meth:
             if not return_type_info.java_hu_ty.startswith("Result_" + struct_meth):
-                method_name = orig_method_name
+                struct_meth_name = method_name
                 struct_meth = ""
+                expected_struct = ""
 
         out_java.write("\t// " + line)
         (out_java_delta, out_c_delta, out_java_struct_delta) = \
-            consts.map_function(argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, takes_self_ptr, args_known, type_mapping_generator, doc_comment)
+            consts.map_function(argument_types, c_call_string, method_name, struct_meth_name, return_type_info, struct_meth, default_constructor_args, takes_self, takes_self_ptr, args_known, type_mapping_generator, doc_comment)
         out_java.write(out_java_delta)
 
         if is_free:
@@ -522,11 +494,9 @@ with open(sys.argv[1]) as in_h, open(f"{sys.argv[2]}/bindings{consts.file_ext}",
             write_c(out_c_delta)
 
         out_java_struct = None
-        expected_struct = "LDK" + struct_meth
-        expected_cstruct = "LDKC" + struct_meth
         if (expected_struct in opaque_structs or expected_struct in trait_structs
-                or expected_struct in complex_enums or expected_cstruct in complex_enums
-                or expected_cstruct in result_types) and not is_free:
+                or expected_struct in complex_enums or expected_struct in complex_enums
+                or expected_struct in result_types or expected_struct in tuple_types) and not is_free:
             out_java_struct = open(f"{sys.argv[3]}/structs/{struct_meth}{consts.file_ext}", "a")
             out_java_struct.write(out_java_struct_delta)
         elif (not is_free and not method_name.endswith("_clone") and
@@ -756,47 +726,64 @@ with open(sys.argv[1]) as in_h, open(f"{sys.argv[2]}/bindings{consts.file_ext}",
     def map_tuple(struct_name, field_lines):
         out_java.write("\tpublic static native long " + struct_name + "_new(")
         write_c(consts.c_fn_ty_pfx + consts.ptr_c_ty + " " + consts.c_fn_name_define_pfx(struct_name + "_new", len(field_lines) > 3))
-        ty_list = []
-        for idx, (line, _) in enumerate(field_lines):
-            if idx != 0 and idx < len(field_lines) - 2:
-                ty_info = java_c_types(line.strip(';'), None)
-                if idx != 1:
-                    out_java.write(", ")
-                    write_c(", ")
-                e = chr(ord('a') + idx - 1)
-                out_java.write(ty_info.java_ty + " " + e)
-                write_c(ty_info.c_ty + " " + e)
-                ty_list.append(ty_info)
-        tuple_types[struct_name] = (ty_list, struct_name)
-        out_java.write(");\n")
-        write_c(") {\n")
-        write_c("\t" + struct_name + "* ret = MALLOC(sizeof(" + struct_name + "), \"" + struct_name + "\");\n")
+        human_ty = struct_name.replace("LDKC2Tuple", "TwoTuple").replace("LDKC3Tuple", "ThreeTuple")
+        with open(f"{sys.argv[3]}/structs/{human_ty}{consts.file_ext}", "w") as out_java_struct:
+            out_java_struct.write(consts.map_tuple(struct_name))
+            ty_list = []
+            for idx, (line, _) in enumerate(field_lines):
+                if idx != 0 and idx < len(field_lines) - 2:
+                    ty_info = java_c_types(line.strip(';'), None)
+                    if idx != 1:
+                        out_java.write(", ")
+                        write_c(", ")
+                    e = chr(ord('a') + idx - 1)
+                    out_java.write(ty_info.java_ty + " " + e)
+                    write_c(ty_info.c_ty + " " + e)
+                    ty_list.append(ty_info)
+            tuple_types[struct_name] = (ty_list, struct_name)
+            out_java.write(");\n")
+            write_c(") {\n")
+            write_c("\t" + struct_name + "* ret = MALLOC(sizeof(" + struct_name + "), \"" + struct_name + "\");\n")
+            for idx, (line, _) in enumerate(field_lines):
+                if idx != 0 and idx < len(field_lines) - 2:
+                    ty_info = type_mapping_generator.map_type(line.strip(';'), False, None, False, False)
+                    e = chr(ord('a') + idx - 1)
+                    if ty_info.arg_conv is not None:
+                        write_c("\t" + ty_info.arg_conv.replace("\n", "\n\t"))
+                        write_c("\n\tret->" + e + " = " + ty_info.arg_conv_name + ";\n")
+                    else:
+                        write_c("\tret->" + e + " = " + e + ";\n")
+                    if ty_info.arg_conv_cleanup is not None:
+                        write_c("\t//TODO: Really need to call " + ty_info.arg_conv_cleanup + " here\n")
+            write_c("\treturn (uint64_t)ret;\n")
+            write_c("}\n")
+
+        # Map virtual getter functions
         for idx, (line, _) in enumerate(field_lines):
             if idx != 0 and idx < len(field_lines) - 2:
-                ty_info = type_mapping_generator.map_type(line.strip(';'), False, None, False, False)
-                e = chr(ord('a') + idx - 1)
-                if ty_info.arg_conv is not None:
-                    write_c("\t" + ty_info.arg_conv.replace("\n", "\n\t"))
-                    write_c("\n\tret->" + e + " = " + ty_info.arg_conv_name + ";\n")
+                field_name = chr(ord('a') + idx - 1)
+                assert line.endswith(" " + field_name + ";")
+                field_ty = java_c_types(line[:-1], None)
+                ptr_fn_defn = line[:-3].strip() + " *" + struct_name.replace("LDK", "") + "_get_" + field_name + "(" + struct_name + " *NONNULL_PTR tuple)"
+                owned_fn_defn = line[:-3].strip() + " " + struct_name.replace("LDK", "") + "_get_" + field_name + "(" + struct_name + " *NONNULL_PTR tuple)"
+
+                holds_ref = False
+                if field_ty.rust_obj is not None and field_ty.rust_obj.replace("LDK", "") + "_clone" in clone_fns:
+                    fn_defn = owned_fn_defn
+                    write_c("static inline " + fn_defn + "{\n")
+                    write_c("\treturn " + field_ty.rust_obj.replace("LDK", "") + "_clone(&tuple->" + field_name + ");\n")
+                elif field_ty.arr_len is not None or field_ty.is_native_primitive:
+                    fn_defn = owned_fn_defn
+                    write_c("static inline " + fn_defn + "{\n")
+                    write_c("\treturn tuple->" + field_name + ";\n")
                 else:
-                    write_c("\tret->" + e + " = " + e + ";\n")
-                if ty_info.arg_conv_cleanup is not None:
-                    write_c("\t//TODO: Really need to call " + ty_info.arg_conv_cleanup + " here\n")
-        write_c("\treturn (uint64_t)ret;\n")
-        write_c("}\n")
-
-        for idx, ty_info in enumerate(ty_list):
-            e = chr(ord('a') + idx)
-            out_java.write("\tpublic static native " + ty_info.java_ty + " " + struct_name + "_get_" + e + "(long ptr);\n")
-            write_c(consts.c_fn_ty_pfx + ty_info.c_ty + " " + consts.c_fn_name_define_pfx(struct_name + "_get_" + e, True) + consts.ptr_c_ty + " ptr) {\n")
-            write_c("\t" + struct_name + " *tuple = (" + struct_name + "*)(ptr & ~1);\n")
-            conv_info = type_mapping_generator.map_type_with_info(ty_info, False, None, False, True)
-            if conv_info.ret_conv is not None:
-                write_c("\t" + conv_info.ret_conv[0].replace("\n", "\n\t") + "tuple->" + e + conv_info.ret_conv[1].replace("\n", "\n\t") + "\n")
-                write_c("\treturn " + conv_info.ret_conv_name + ";\n")
-            else:
-                write_c("\treturn tuple->" + e + ";\n")
-            write_c("}\n")
+                    fn_defn = ptr_fn_defn
+                    write_c("static inline " + fn_defn + "{\n")
+                    write_c("\treturn &tuple->" + field_name + ";\n")
+                    holds_ref = True
+                write_c("}\n")
+                dummy_line = fn_defn + ";\n"
+                map_fn_with_ref_option(dummy_line, reg_fn_regex.match(dummy_line), None, None, "", holds_ref)
 
     out_java.write(consts.bindings_header)
     with open(f"{sys.argv[2]}/version{consts.file_ext}", "w") as out_java_version:
@@ -1087,6 +1074,10 @@ with open(sys.argv[1]) as in_h, open(f"{sys.argv[2]}/bindings{consts.file_ext}",
     for struct_name in result_types:
         with open(f"{sys.argv[3]}/structs/{struct_name.replace('LDKCResult', 'Result')}{consts.file_ext}", "a") as out_java_struct:
             out_java_struct.write("}\n")
+    for struct_name in tuple_types:
+        struct_hu_name = struct_name.replace("LDKC2Tuple", "TwoTuple").replace("LDKC3Tuple", "ThreeTuple")
+        with open(f"{sys.argv[3]}/structs/{struct_hu_name}{consts.file_ext}", "a") as out_java_struct:
+            out_java_struct.write("}\n")
 
 with open(f"{sys.argv[4]}/bindings.c.body", "w") as out_c:
     out_c.write(consts.c_file_pfx)
index 5452829d70275e4e547bcf47dfc50fc2dba4df44..d2054a172237019f84284beceab2b31834dca60e 100644 (file)
@@ -1112,11 +1112,12 @@ import javax.annotation.Nullable;
         out_opaque_struct_human += self.hu_struct_file_prefix
         out_opaque_struct_human += "\n/**\n * " + struct_doc_comment.replace("\n", "\n * ") + "\n */\n"
         out_opaque_struct_human += "@SuppressWarnings(\"unchecked\") // We correctly assign various generic arrays\n"
-        out_opaque_struct_human += ("public class " + struct_name.replace("LDK","") + " extends CommonBase")
+        hu_name = struct_name.replace("LDKC2Tuple", "TwoTuple").replace("LDKC3Tuple", "ThreeTuple").replace("LDK", "")
+        out_opaque_struct_human += ("public class " + hu_name + " extends CommonBase")
         if struct_name.startswith("LDKLocked"):
             out_opaque_struct_human += (" implements AutoCloseable")
         out_opaque_struct_human += (" {\n")
-        out_opaque_struct_human += ("\t" + struct_name.replace("LDK", "") + "(Object _dummy, long ptr) { super(ptr); }\n")
+        out_opaque_struct_human += ("\t" + hu_name + "(Object _dummy, long ptr) { super(ptr); }\n")
         if struct_name.startswith("LDKLocked"):
             out_opaque_struct_human += ("\t@Override public void close() {\n")
         else:
@@ -1127,8 +1128,10 @@ import javax.annotation.Nullable;
         out_opaque_struct_human += ("\t}\n\n")
         return out_opaque_struct_human
 
+    def map_tuple(self, struct_name):
+        return self.map_opaque_struct(struct_name, "A Tuple")
 
-    def map_function(self, argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, takes_self_as_ref, args_known, type_mapping_generator, doc_comment):
+    def map_function(self, argument_types, c_call_string, method_name, meth_n, return_type_info, struct_meth, default_constructor_args, takes_self, takes_self_as_ref, args_known, type_mapping_generator, doc_comment):
         out_java = ""
         out_c = ""
         out_java_struct = None
@@ -1155,7 +1158,6 @@ import javax.annotation.Nullable;
         if not args_known:
             out_java_struct += ("\t// Skipped " + method_name + "\n")
         else:
-            meth_n = method_name[len(struct_meth) + 1 if len(struct_meth) != 0 else 0:].strip("_")
             if doc_comment is not None:
                 out_java_struct += "\t/**\n\t * " + doc_comment.replace("\n", "\n\t * ") + "\n\t */\n"
             if return_type_info.nullable:
index f823e6cb7274ecfe81907d7ecc85fdd604dfb273..c097921f7d43de5ebc733be09392e1b24e19a6e4 100644 (file)
@@ -939,7 +939,10 @@ const decodeString = (stringPointer, free = true) => {
 """
         return out_opaque_struct_human
 
-    def map_function(self, argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, takes_self_as_ref, args_known, type_mapping_generator, doc_comment):
+    def map_tuple(self, struct_name):
+        return self.map_opaque_struct(struct_name, "A Tuple")
+
+    def map_function(self, argument_types, c_call_string, method_name, meth_n, return_type_info, struct_meth, default_constructor_args, takes_self, takes_self_as_ref, args_known, type_mapping_generator, doc_comment):
         out_java = ""
         out_c = ""
         out_java_struct = None
@@ -992,7 +995,6 @@ const decodeString = (stringPointer, free = true) => {
         if not args_known:
             out_java_struct += ("\t// Skipped " + method_name + "\n")
         else:
-            meth_n = method_name[len(struct_meth) + 1:]
             if not takes_self:
                 out_java_struct += (
                         "\tpublic static " + return_type_info.java_hu_ty + " constructor_" + meth_n + "(")