X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=genbindings.py;h=c46644b8ee746eb76a801db18c4bf2c44eff2f1c;hb=5db028343219410723b62a7feee5f9aaa159de5b;hp=e8cde68359c1f75597d1f6f487978c9a89ba2018;hpb=c2ba63528fc9ee75ca3fd07d7e7c490435ac4542;p=ldk-java diff --git a/genbindings.py b/genbindings.py index e8cde683..c46644b8 100755 --- a/genbindings.py +++ b/genbindings.py @@ -70,6 +70,14 @@ def camel_to_snake(s): lastund = True return (ret + lastchar.lower()).strip("_") +def doc_to_field_nullable(doc): + if doc is None: + return False + for line in doc.splitlines(): + if "Note that this (or a relevant inner pointer) may be NULL or all-0s to represent None" in line: + return True + return False + def doc_to_params_ret_nullable(doc): if doc is None: return (set(), False) @@ -92,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): @@ -296,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() @@ -416,26 +385,36 @@ java_c_types_none_allowed = False # C structs created by cbindgen are declared i 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(sys.argv[2], "w") as out_java: +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] - - return_type_info = type_mapping_generator.map_type(method_return_type.strip() + " ret", True, ret_arr_len, False, False) + 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.nullable = True + 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) argument_types = [] default_constructor_args = {} @@ -444,15 +423,35 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: args_known = True for argument_index, argument in enumerate(method_arguments): - argument_conversion_info = type_mapping_generator.map_type(argument, False, None, is_free, True) - if argument_index == 0 and argument_conversion_info.java_hu_ty == struct_meth: + 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 argument_conversion_info.arg_name in params_nullable: - argument_conversion_info.nullable = 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.") + 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: - assert not argument_conversion_info.arg_name in params_nullable 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(','): @@ -468,12 +467,13 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: 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: @@ -499,14 +499,13 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: 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 + not method_name.startswith("TxOut") and not method_name.startswith("_") and method_name != "check_platform" and method_name != "Result_read" and not expected_struct in unitary_enums and @@ -523,7 +522,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: assert struct_name.startswith("LDK") with open(f"{sys.argv[3]}/enums/{struct_name[3:]}{consts.file_ext}", "w") as out_java_enum: unitary_enums.add(struct_name) - for idx, struct_line in enumerate(field_lines): + for idx, (struct_line, _) in enumerate(field_lines): if idx == 0: assert(struct_line == "typedef enum %s {" % struct_name) elif idx == len(field_lines) - 3: @@ -533,7 +532,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: elif idx == len(field_lines) - 1: assert(struct_line == "") assert struct_name.startswith("LDK") - (c_out, native_file_out, native_out) = consts.native_c_unitary_enum_map(struct_name[3:], [x.strip().strip(",") for x in field_lines[1:-3]], enum_doc_comment) + (c_out, native_file_out, native_out) = consts.native_c_unitary_enum_map(struct_name[3:], [x.strip().strip(",") for x, _ in field_lines[1:-3]], enum_doc_comment) write_c(c_out) out_java_enum.write(native_file_out) out_java.write(native_out) @@ -544,7 +543,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: enum_variants = [] tag_field_lines = union_enum_items["field_lines"] - for idx, struct_line in enumerate(tag_field_lines): + for idx, (struct_line, _) in enumerate(tag_field_lines): if idx == 0: assert(struct_line == "typedef enum %s_Tag {" % struct_name) elif idx == len(tag_field_lines) - 3: @@ -558,12 +557,19 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: fields = [] if "LDK" + variant_name in union_enum_items: enum_var_lines = union_enum_items["LDK" + variant_name] - for idx, field in enumerate(enum_var_lines): + for idx, (field, field_docs) in enumerate(enum_var_lines): if idx != 0 and idx < len(enum_var_lines) - 2 and field.strip() != "": - fields.append(type_mapping_generator.map_type(field.strip(' ;'), False, None, False, True)) + field_ty = type_mapping_generator.java_c_types(field.strip(' ;'), None) + if field_docs is not None and doc_to_field_nullable(field_docs): + field_conv = type_mapping_generator.map_type_with_info(field_ty, False, None, False, True, True) + else: + field_conv = type_mapping_generator.map_type_with_info(field_ty, False, None, False, True, False) + fields.append((field_conv, field_docs)) enum_variants.append(ComplexEnumVariantInfo(variant_name, fields, False)) elif camel_to_snake(variant_name) in inline_enum_variants: - fields.append(type_mapping_generator.map_type(inline_enum_variants[camel_to_snake(variant_name)] + " " + camel_to_snake(variant_name), False, None, False, True)) + # TODO: If we ever have a rust enum Variant(Option) we need to pipe + # docs through to there, and then potentially mark the field nullable. + fields.append((type_mapping_generator.map_type(inline_enum_variants[camel_to_snake(variant_name)] + " " + camel_to_snake(variant_name), False, None, False, True), None)) enum_variants.append(ComplexEnumVariantInfo(variant_name, fields, True)) else: enum_variants.append(ComplexEnumVariantInfo(variant_name, fields, True)) @@ -596,22 +602,25 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: ret_ty_info = type_mapping_generator.map_type("void", True, None, False, False) field_fns.append(TraitMethInfo("cloned", False, ret_ty_info, [], fn_docs)) else: - ret_ty_info = type_mapping_generator.map_type(fn_line.group(2).strip() + " ret", True, None, False, False) - is_const = fn_line.group(4) is not None (nullable_params, ret_nullable) = doc_to_params_ret_nullable(fn_docs) if ret_nullable: assert False # This isn't yet handled on the Java side ret_ty_info.nullable = True + ret_ty_info = type_mapping_generator.map_nullable_type(fn_line.group(2).strip() + " ret", True, None, False, False) + else: + ret_ty_info = type_mapping_generator.map_type(fn_line.group(2).strip() + " ret", True, None, False, False) + is_const = fn_line.group(4) is not None arg_tys = [] for idx, arg in enumerate(fn_line.group(5).split(',')): if arg == "": continue - arg_conv_info = type_mapping_generator.map_type(arg, True, None, False, False) - if arg_conv_info.arg_name in nullable_params: + arg_ty_info = type_mapping_generator.java_c_types(arg, None) + if arg_ty_info.var_name in nullable_params: # Types that are actually null instead of all-0s aren't yet handled on the Java side: - assert arg_conv_info.rust_obj == "LDKPublicKey" - arg_conv_info.nullable = True + arg_conv_info = type_mapping_generator.map_type_with_info(arg_ty_info, True, None, False, False, True) + else: + arg_conv_info = type_mapping_generator.map_type_with_info(arg_ty_info, True, None, False, False, False) arg_tys.append(arg_conv_info) field_fns.append(TraitMethInfo(fn_line.group(3), is_const, ret_ty_info, arg_tys, fn_docs)) @@ -725,51 +734,45 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: out_java_struct.write("\t}\n\n") 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") - for idx, line in enumerate(field_lines): + 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_list.append(java_c_types(line.strip(';'), None)) + tuple_types[struct_name] = (ty_list, struct_name) + + # 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.replace('', local_git_version)) + out_java.write(consts.bindings_header) + with open(f"{sys.argv[2]}/version{consts.file_ext}", "w") as out_java_version: + out_java_version.write(consts.bindings_version_file.replace('', local_git_version)) with open(f"{sys.argv[3]}/structs/CommonBase{consts.file_ext}", "w") as out_java_struct: out_java_struct.write(consts.common_base) @@ -820,6 +823,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: is_tuple = False trait_fn_lines = [] field_var_lines = [] + last_struct_block_comment = None for idx, struct_line in enumerate(obj_lines): if struct_line.strip().startswith("/*"): @@ -860,7 +864,8 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: field_var_match = line_field_var_regex.match(struct_line) if field_var_match is not None: field_var_lines.append(field_var_match) - field_lines.append(struct_line) + field_lines.append((struct_line, last_struct_block_comment)) + last_struct_block_comment = None assert(struct_name is not None) assert(len(trait_fn_lines) == 0 or not (is_opaque or is_unitary_enum or is_union_enum or is_union or result_contents is not None or vec_ty is not None)) @@ -882,7 +887,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: res_ty, err_ty = result_ptr_struct_items[result_contents] map_result(struct_name, res_ty, err_ty) elif struct_name.startswith("LDKCResult_") and struct_name.endswith("ZPtr"): - for line in field_lines: + for line, _ in field_lines: if line.endswith("*result;"): res_ty = line[:-8].strip() elif line.endswith("*err;"): @@ -944,7 +949,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: elif struct_name in union_enum_items: tuple_variants = {} elem_items = -1 - for line in field_lines: + for line, _ in field_lines: if line == " struct {": elem_items = 0 elif line == " };": @@ -973,15 +978,39 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: with open(f"{sys.argv[3]}/structs/TxOut{consts.file_ext}", "w") as out_java_struct: out_java_struct.write(consts.hu_struct_file_prefix) out_java_struct.write("public class TxOut extends CommonBase{\n") - out_java_struct.write("\tTxOut(java.lang.Object _dummy, long ptr) { super(ptr); }\n") - out_java_struct.write("\tlong to_c_ptr() { return 0; }\n") + out_java_struct.write("\t/** The script_pubkey in this output */\n") + out_java_struct.write("\tpublic final byte[] script_pubkey;\n") + out_java_struct.write("\t/** The value, in satoshis, of this output */\n") + out_java_struct.write("\tpublic final long value;\n") + out_java_struct.write("\n") + out_java_struct.write("\tTxOut(java.lang.Object _dummy, long ptr) {\n") + out_java_struct.write("\t\tsuper(ptr);\n") + out_java_struct.write("\t\tthis.script_pubkey = bindings.TxOut_get_script_pubkey(ptr);\n") + out_java_struct.write("\t\tthis.value = bindings.TxOut_get_value(ptr);\n") + out_java_struct.write("\t}\n") + out_java_struct.write("\tpublic TxOut(long value, byte[] script_pubkey) {\n") + out_java_struct.write("\t\tsuper(bindings.TxOut_new(script_pubkey, value));\n") + out_java_struct.write("\t\tthis.script_pubkey = bindings.TxOut_get_script_pubkey(ptr);\n") + out_java_struct.write("\t\tthis.value = bindings.TxOut_get_value(ptr);\n") + out_java_struct.write("\t}\n") + out_java_struct.write("\n") out_java_struct.write("\t@Override @SuppressWarnings(\"deprecation\")\n") out_java_struct.write("\tprotected void finalize() throws Throwable {\n") out_java_struct.write("\t\tsuper.finalize();\n") out_java_struct.write("\t\tif (ptr != 0) { bindings.TxOut_free(ptr); }\n") out_java_struct.write("\t}\n") - # TODO: TxOut body + out_java_struct.write("\n") out_java_struct.write("}") + fn_line = "struct LDKCVec_u8Z TxOut_get_script_pubkey (struct LDKTxOut* thing)" + write_c(fn_line + " {") + write_c("\treturn CVec_u8Z_clone(&thing->script_pubkey);") + write_c("}") + map_fn(fn_line + "\n", re.compile("(.*) (TxOut_get_script_pubkey) \((.*)\)").match(fn_line), None, None, None) + fn_line = "uint64_t TxOut_get_value (struct LDKTxOut* thing)" + write_c(fn_line + " {") + write_c("\treturn thing->value;") + write_c("}") + map_fn(fn_line + "\n", re.compile("(.*) (TxOut_get_value) \((.*)\)").match(fn_line), None, None, None) else: pass # Everything remaining is a byte[] or some form cur_block_obj = None @@ -1030,10 +1059,16 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: 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(sys.argv[4], "w") as out_c: - out_c.write(consts.c_file_pfx.replace('', local_git_version)) +with open(f"{sys.argv[4]}/bindings.c.body", "w") as out_c: + out_c.write(consts.c_file_pfx) out_c.write(consts.init_str()) out_c.write(c_file) +with open(f"{sys.argv[4]}/version.c", "w") as out_c: + out_c.write(consts.c_version_file.replace('', local_git_version)) with open(f"{sys.argv[3]}/structs/UtilMethods{consts.file_ext}", "a") as util: util.write(consts.util_fn_sfx)