+ rty = java_c_types(reg_fn.group(1), None)
+ if rty is not None and not rty.is_native_primitive and reg_fn.group(2) == rty.java_hu_ty + "_new":
+ constructor_fns[rty.rust_obj] = reg_fn.group(3)
+ continue
+ arr_fn = fn_ret_arr_regex.match(line)
+ if arr_fn is not None:
+ if arr_fn.group(2).endswith("_clone"):
+ clone_fns.add(arr_fn.group(2))
+ # No object constructors return arrays, as then they wouldn't be an object constructor
+ continue
+
+# Define some manual clones...
+clone_fns.add("ThirtyTwoBytes_clone")
+write_c("static inline struct LDKThirtyTwoBytes ThirtyTwoBytes_clone(const struct LDKThirtyTwoBytes *orig) { struct LDKThirtyTwoBytes ret; memcpy(ret.data, orig->data, 32); return ret; }\n")
+
+java_c_types_none_allowed = False # C structs created by cbindgen are declared in dependency order
+
+with open(f"{sys.argv[3]}/structs/UtilMethods{consts.file_ext}", "a") as util:
+ util.write(consts.util_fn_pfx)
+
+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)
+ method_comma_separated_arguments = re_match.group(3)
+ method_arguments = method_comma_separated_arguments.split(',')
+
+ if method_name.startswith("__"):
+ return
+
+ 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") or method_name.startswith("C3Tuple"):
+ tuple_name = method_name.rsplit("Z", 1)[0][2:] + "Z"
+ if method_name.startswith("C2Tuple"):
+ struct_meth = "Two" + tuple_name
+ expected_struct = "LDKC2" + tuple_name
+ else:
+ struct_meth = "Three" + tuple_name
+ expected_struct = "LDKC3" + 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("_")
+
+ (params_nullable, ret_nullable) = doc_to_params_ret_nullable(doc_comment)
+ if ret_nullable:
+ return_type_info = type_mapping_generator.map_nullable_type(method_return_type.strip() + " ret", True, ret_arr_len, False, force_holds_ref)
+ else:
+ return_type_info = type_mapping_generator.map_type(method_return_type.strip() + " ret", True, ret_arr_len, False, force_holds_ref)
+
+ if method_name.endswith("_clone") and expected_struct not in unitary_enums:
+ meth_line = "uint64_t " + expected_struct.replace("LDK", "") + "_clone_ptr(" + expected_struct + " *NONNULL_PTR arg)"
+ write_c("static inline " + meth_line + " {\n")
+ write_c("\t" + return_type_info.ret_conv[0].replace("\n", "\n\t"))
+ write_c(method_name + "(arg)")
+ write_c(return_type_info.ret_conv[1])
+ write_c("\n\treturn " + return_type_info.ret_conv_name + ";\n}\n")
+ map_fn(meth_line + ";\n", re.compile("(uint64_t) ([A-Za-z_0-9]*)\((.*)\)").match(meth_line), None, None, None)
+
+ argument_types = []
+ default_constructor_args = {}
+ takes_self = False
+ takes_self_ptr = False
+ args_known = True
+
+ for argument_index, argument in enumerate(method_arguments):
+ arg_ty = type_mapping_generator.java_c_types(argument, None)
+ argument_conversion_info = None
+ if argument_index == 0 and arg_ty.java_hu_ty == struct_meth:
+ argument_conversion_info = type_mapping_generator.map_type_with_info(arg_ty, False, None, is_free, True, False)
+ takes_self = True
+ if argument_conversion_info.ty_info.is_ptr:
+ takes_self_ptr = True
+ elif arg_ty.var_name in params_nullable:
+ argument_conversion_info = type_mapping_generator.map_type_with_info(arg_ty, False, None, is_free, True, True)
+ if argument_conversion_info.arg_conv is not None and "Warning" in argument_conversion_info.arg_conv:
+ arg_ty_info = java_c_types(argument, None)
+ print("WARNING: Remapping argument " + arg_ty_info.var_name + " of function " + method_name + " to a reference")
+ print(" The argument appears to require a move, or not clonable, and is nullable.")
+ print(" Normally for arguments that require a move and are not clonable, we split")
+ print(" the argument into the type's constructor's arguments and just use those to")
+ print(" construct a new object on the fly.")
+ print(" However, because the object is nullable, doing so would mean we can no")
+ print(" longer allow the user to pass null, as we now have an argument list instead.")
+ print(" Thus, we blindly assume its really an Option<&Type> instead of an Option<Type>.")
+ print(" It may or may not actually be a reference, but its the simplest mapping option")
+ print(" and also the only use of this code today.")
+ arg_ty_info.requires_clone = False
+ argument_conversion_info = type_mapping_generator.map_type_with_info(arg_ty_info, False, None, is_free, True, True)
+ assert argument_conversion_info.nullable
+ assert argument_conversion_info.arg_conv is not None and "Warning" not in argument_conversion_info.arg_conv
+ else:
+ argument_conversion_info = type_mapping_generator.map_type_with_info(arg_ty, False, None, is_free, True, False)
+
+ if argument_conversion_info.arg_conv is not None and "Warning" in argument_conversion_info.arg_conv:
+ if argument_conversion_info.rust_obj in constructor_fns:
+ assert not is_free
+ for explode_arg in constructor_fns[argument_conversion_info.rust_obj].split(','):
+ explode_arg_conv = type_mapping_generator.map_type(explode_arg, False, None, False, True)
+ if explode_arg_conv.c_ty == "void":
+ # We actually want to handle this case, but for now its only used in NetGraphMsgHandler::new()
+ # which ends up resulting in a redundant constructor - both without arguments for the NetworkGraph.
+ args_known = False
+ pass
+ if not argument_conversion_info.arg_name in default_constructor_args:
+ default_constructor_args[argument_conversion_info.arg_name] = []
+ default_constructor_args[argument_conversion_info.arg_name].append(explode_arg_conv)
+ 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):
+ 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, 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:
+ assert len(argument_types) == 1
+ assert return_type_info.c_ty == "void"
+ write_c(consts.c_fn_ty_pfx + "void " + consts.c_fn_name_define_pfx(method_name, True) + argument_types[0].c_ty + " " + argument_types[0].ty_info.var_name + ") {\n")
+ if argument_types[0].ty_info.passed_as_ptr and not argument_types[0].ty_info.rust_obj in opaque_structs:
+ write_c("\tif ((" + argument_types[0].ty_info.var_name + " & 1) != 0) return;\n")
+
+ for info in argument_types:
+ if info.arg_conv is not None:
+ write_c("\t" + info.arg_conv.replace('\n', "\n\t") + "\n")
+ assert c_call_string is None
+ write_c("\t" + method_name + "(")
+ if argument_types[0].arg_conv_name is not None:
+ write_c(argument_types[0].arg_conv_name)
+ write_c(");")
+ for info in argument_types:
+ if info.arg_conv_cleanup is not None:
+ write_c("\n\t" + info.arg_conv_cleanup.replace("\n", "\n\t"))
+ write_c("\n}\n\n")