X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=genbindings.py;h=2443dac65feaed290d4088dd00ad106f0fb21901;hb=bfbfeced77a2cf3ab06b33fe149666d6db225645;hp=0e20b2a2548f5c6095c89a2b97aa422ac0b139b4;hpb=ee0fbf24cf3365d2e48125c94e2fcc1e277585dc;p=ldk-java diff --git a/genbindings.py b/genbindings.py index 0e20b2a2..2443dac6 100755 --- a/genbindings.py +++ b/genbindings.py @@ -170,6 +170,8 @@ def java_c_types(fn_arg, ret_arr_len): is_primitive = False arr_len = None + mapped_type = [] + java_type_plural = None if fn_arg.startswith("void"): java_ty = "void" c_ty = "void" @@ -183,26 +185,30 @@ def java_c_types(fn_arg, ret_arr_len): fn_arg = fn_arg[4:].strip() is_primitive = True elif fn_arg.startswith("uint8_t"): - java_ty = "byte" + mapped_type = consts.c_type_map['uint8_t'] + java_ty = mapped_type[0] c_ty = "int8_t" fn_ty_arg = "B" fn_arg = fn_arg[7:].strip() is_primitive = True elif fn_arg.startswith("uint16_t"): - java_ty = "short" + mapped_type = consts.c_type_map['uint16_t'] + java_ty = mapped_type[0] c_ty = "jshort" fn_ty_arg = "S" fn_arg = fn_arg[8:].strip() is_primitive = True elif fn_arg.startswith("uint32_t"): - java_ty = "int" + mapped_type = consts.c_type_map['uint32_t'] + java_ty = mapped_type[0] c_ty = "int32_t" fn_ty_arg = "I" fn_arg = fn_arg[8:].strip() is_primitive = True elif fn_arg.startswith("uint64_t") or fn_arg.startswith("uintptr_t"): # TODO: uintptr_t is arch-dependent :( - java_ty = "long" + mapped_type = consts.c_type_map['long'] + java_ty = mapped_type[0] c_ty = "int64_t" fn_ty_arg = "J" if fn_arg.startswith("uint64_t"): @@ -295,7 +301,11 @@ def java_c_types(fn_arg, ret_arr_len): if var_is_arr is not None or ret_arr_len is not None: assert(not take_by_ptr) assert(not is_ptr) - java_ty = java_ty + "[]" + # is there a special case for plurals? + if len(mapped_type) == 2: + java_ty = mapped_type[1] + else: + java_ty = java_ty + "[]" c_ty = c_ty + "Array" if var_is_arr is not None: if var_is_arr.group(1) == "": @@ -924,12 +934,40 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: write_c(c_out) out_java_enum.write(native_file_out) out_java.write(native_out) - + def map_complex_enum(struct_name, union_enum_items): java_hu_type = struct_name.replace("LDK", "") complex_enums.add(struct_name) + + enum_variants = [] + tag_field_lines = union_enum_items["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: + assert(struct_line.endswith("_Sentinel,")) + elif idx == len(tag_field_lines) - 2: + assert(struct_line == "} %s_Tag;" % struct_name) + elif idx == len(tag_field_lines) - 1: + assert(struct_line == "") + else: + variant_name = struct_line.strip(' ,')[len(struct_name) + 1:] + 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): + if idx != 0 and idx < len(enum_var_lines) - 2: + fields.append(map_type(field.strip(' ;'), False, None, False, True)) + else: + # TODO: Assert line format + pass + else: + # TODO: Assert line format + pass + enum_variants.append(ComplexEnumVariantInfo(variant_name, fields)) + with open(f"{sys.argv[3]}/structs/{java_hu_type}{consts.file_ext}", "w") as out_java_enum: - (out_java_addendum, out_java_enum_addendum, out_c_addendum) = consts.map_complex_enum(struct_name, union_enum_items, map_type, camel_to_snake) + (out_java_addendum, out_java_enum_addendum, out_c_addendum) = consts.map_complex_enum(struct_name, enum_variants, camel_to_snake) out_java_enum.write(out_java_enum_addendum) out_java.write(out_java_addendum) @@ -957,208 +995,10 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: arg_tys.append(arg_conv_info) field_fns.append(TraitMethInfo(fn_line.group(3), is_const, ret_ty_info, arg_tys)) - write_c(consts.native_c_map_trait(struct_name, field_var_convs, field_fns)[1]) - - out_java_trait.write(consts.hu_struct_file_prefix) - out_java_trait.write("public class " + struct_name.replace("LDK","") + " extends CommonBase {\n") - out_java_trait.write("\tfinal bindings." + struct_name + " bindings_instance;\n") - out_java_trait.write("\t" + struct_name.replace("LDK", "") + "(Object _dummy, long ptr) { super(ptr); bindings_instance = null; }\n") - out_java_trait.write("\tprivate " + struct_name.replace("LDK", "") + "(bindings." + struct_name + " arg") - for idx, var_line in enumerate(field_var_lines): - if var_line.group(1) in trait_structs: - out_java_trait.write(", bindings." + var_line.group(1) + " " + var_line.group(2)) - else: - out_java_trait.write(", " + field_var_convs[idx].java_hu_ty + " " + var_line.group(2)) - out_java_trait.write(") {\n") - out_java_trait.write("\t\tsuper(bindings." + struct_name + "_new(arg") - for idx, var_line in enumerate(field_var_lines): - if var_line.group(1) in trait_structs: - out_java_trait.write(", " + var_line.group(2)) - elif field_var_convs[idx].from_hu_conv is not None: - out_java_trait.write(", " + field_var_convs[idx].from_hu_conv[0]) - else: - out_java_trait.write(", " + var_line.group(2)) - out_java_trait.write("));\n") - out_java_trait.write("\t\tthis.ptrs_to.add(arg);\n") - for idx, var_line in enumerate(field_var_lines): - if var_line.group(1) in trait_structs: - out_java_trait.write("\t\tthis.ptrs_to.add(" + var_line.group(2) + ");\n") - elif field_var_convs[idx].from_hu_conv is not None and field_var_convs[idx].from_hu_conv[1] != "": - out_java_trait.write("\t\t" + field_var_convs[idx].from_hu_conv[1] + ";\n") - out_java_trait.write("\t\tthis.bindings_instance = arg;\n") - out_java_trait.write("\t}\n") - out_java_trait.write("\t@Override @SuppressWarnings(\"deprecation\")\n") - out_java_trait.write("\tprotected void finalize() throws Throwable {\n") - out_java_trait.write("\t\tif (ptr != 0) { bindings." + struct_name.replace("LDK","") + "_free(ptr); } super.finalize();\n") - out_java_trait.write("\t}\n\n") - - java_trait_constr = "\tprivate static class " + struct_name + "Holder { " + struct_name.replace("LDK", "") + " held; }\n" - java_trait_constr = java_trait_constr + "\tpublic static " + struct_name.replace("LDK", "") + " new_impl(" + struct_name.replace("LDK", "") + "Interface arg" - for idx, var_line in enumerate(field_var_lines): - if var_line.group(1) in trait_structs: - # Ideally we'd be able to take any instance of the interface, but our C code can only represent - # Java-implemented version, so we require users pass a Java implementation here :/ - java_trait_constr = java_trait_constr + ", " + var_line.group(1).replace("LDK", "") + "." + var_line.group(1).replace("LDK", "") + "Interface " + var_line.group(2) + "_impl" - else: - java_trait_constr = java_trait_constr + ", " + field_var_convs[idx].java_hu_ty + " " + var_line.group(2) - java_trait_constr = java_trait_constr + ") {\n\t\tfinal " + struct_name + "Holder impl_holder = new " + struct_name + "Holder();\n" - java_trait_constr = java_trait_constr + "\t\timpl_holder.held = new " + struct_name.replace("LDK", "") + "(new bindings." + struct_name + "() {\n" - out_java_trait.write("\tpublic static interface " + struct_name.replace("LDK", "") + "Interface {\n") - out_java.write("\tpublic interface " + struct_name + " {\n") - java_meths = [] - for fn_line in trait_fn_lines: - java_meth_descr = "(" - if fn_line.group(3) != "free" and fn_line.group(3) != "clone": - ret_ty_info = map_type(fn_line.group(2), True, None, False, False) - - out_java.write("\t\t " + ret_ty_info.java_ty + " " + fn_line.group(3) + "(") - java_trait_constr = java_trait_constr + "\t\t\t@Override public " + ret_ty_info.java_ty + " " + fn_line.group(3) + "(" - out_java_trait.write("\t\t" + ret_ty_info.java_hu_ty + " " + fn_line.group(3) + "(") - is_const = fn_line.group(4) is not None - - arg_names = [] - for idx, arg in enumerate(fn_line.group(5).split(',')): - if arg == "": - continue - if idx >= 2: - out_java.write(", ") - java_trait_constr = java_trait_constr + ", " - out_java_trait.write(", ") - arg_conv_info = map_type(arg, True, None, False, False) - out_java.write(arg_conv_info.java_ty + " " + arg_conv_info.arg_name) - out_java_trait.write(arg_conv_info.java_hu_ty + " " + arg_conv_info.arg_name) - java_trait_constr = java_trait_constr + arg_conv_info.java_ty + " " + arg_conv_info.arg_name - arg_names.append(arg_conv_info) - java_meth_descr = java_meth_descr + arg_conv_info.java_fn_ty_arg - java_meth_descr = java_meth_descr + ")" + ret_ty_info.java_fn_ty_arg - java_meths.append((fn_line, java_meth_descr)) - - out_java.write(");\n") - out_java_trait.write(");\n") - java_trait_constr = java_trait_constr + ") {\n" - - for arg_info in arg_names: - if arg_info.to_hu_conv is not None: - java_trait_constr = java_trait_constr + "\t\t\t\t" + arg_info.to_hu_conv.replace("\n", "\n\t\t\t\t") + "\n" - - if ret_ty_info.java_ty != "void": - java_trait_constr = java_trait_constr + "\t\t\t\t" + ret_ty_info.java_hu_ty + " ret = arg." + fn_line.group(3) + "(" - else: - java_trait_constr = java_trait_constr + "\t\t\t\targ." + fn_line.group(3) + "(" - - for idx, arg_info in enumerate(arg_names): - if idx != 0: - java_trait_constr = java_trait_constr + ", " - if arg_info.to_hu_conv_name is not None: - java_trait_constr = java_trait_constr + arg_info.to_hu_conv_name - else: - java_trait_constr = java_trait_constr + arg_info.arg_name - - java_trait_constr = java_trait_constr + ");\n" - if ret_ty_info.java_ty != "void": - if ret_ty_info.from_hu_conv is not None: - java_trait_constr = java_trait_constr + "\t\t\t\t" + ret_ty_info.java_ty + " result = " + ret_ty_info.from_hu_conv[0] + ";\n" - if ret_ty_info.from_hu_conv[1] != "": - java_trait_constr = java_trait_constr + "\t\t\t\t" + ret_ty_info.from_hu_conv[1].replace("this", "impl_holder.held") + ";\n" - if ret_ty_info.rust_obj in result_types: - # Avoid double-free by breaking the result - we should learn to clone these and then we can be safe instead - java_trait_constr = java_trait_constr + "\t\t\t\tret.ptr = 0;\n" - java_trait_constr = java_trait_constr + "\t\t\t\treturn result;\n" - else: - java_trait_constr = java_trait_constr + "\t\t\t\treturn ret;\n" - java_trait_constr = java_trait_constr + "\t\t\t}\n" - java_trait_constr = java_trait_constr + "\t\t}" - for var_line in field_var_lines: - if var_line.group(1) in trait_structs: - java_trait_constr = java_trait_constr + ", " + var_line.group(2) + ".new_impl(" + var_line.group(2) + "_impl).bindings_instance" - else: - java_trait_constr = java_trait_constr + ", " + var_line.group(2) - out_java_trait.write("\t}\n") - out_java_trait.write(java_trait_constr + ");\n\t\treturn impl_holder.held;\n\t}\n") - - # Write out a clone function whether we need one or not, as we use them in moving to rust - write_c("static void* " + struct_name + "_JCalls_clone(const void* this_arg) {\n") - write_c("\t" + struct_name + "_JCalls *j_calls = (" + struct_name + "_JCalls*) this_arg;\n") - write_c("\tatomic_fetch_add_explicit(&j_calls->refcnt, 1, memory_order_release);\n") - for var_line in field_var_lines: - if var_line.group(1) in trait_structs: - write_c("\tatomic_fetch_add_explicit(&j_calls->" + var_line.group(2) + "->refcnt, 1, memory_order_release);\n") - write_c("\treturn (void*) this_arg;\n") - write_c("}\n") - - out_java.write("\t}\n") - - out_java.write("\tpublic static native long " + struct_name + "_new(" + struct_name + " impl") - write_c("static inline " + struct_name + " " + struct_name + "_init (" + consts.c_fn_args_pfx + ", jobject o") - for idx, var_line in enumerate(field_var_lines): - if var_line.group(1) in trait_structs: - out_java.write(", " + var_line.group(1) + " " + var_line.group(2)) - write_c(", jobject " + var_line.group(2)) - else: - out_java.write(", " + field_var_convs[idx].java_ty + " " + var_line.group(2)) - write_c(", " + field_var_convs[idx].c_ty + " " + var_line.group(2)) - out_java.write(");\n") - write_c(") {\n") - - write_c("\tjclass c = (*env)->GetObjectClass(env, o);\n") - write_c("\tCHECK(c != NULL);\n") - write_c("\t" + struct_name + "_JCalls *calls = MALLOC(sizeof(" + struct_name + "_JCalls), \"" + struct_name + "_JCalls\");\n") - write_c("\tatomic_init(&calls->refcnt, 1);\n") - write_c("\tDO_ASSERT((*env)->GetJavaVM(env, &calls->vm) == 0);\n") - write_c("\tcalls->o = (*env)->NewWeakGlobalRef(env, o);\n") - for (fn_line, java_meth_descr) in java_meths: - if fn_line.group(3) != "free" and fn_line.group(3) != "clone": - write_c("\tcalls->" + fn_line.group(3) + "_meth = (*env)->GetMethodID(env, c, \"" + fn_line.group(3) + "\", \"" + java_meth_descr + "\");\n") - write_c("\tCHECK(calls->" + fn_line.group(3) + "_meth != NULL);\n") - for idx, var_line in enumerate(field_var_lines): - if var_line.group(1) not in trait_structs and field_var_convs[idx].arg_conv is not None: - write_c("\n\t" + field_var_convs[idx].arg_conv.replace("\n", "\n\t") +"\n") - write_c("\n\t" + struct_name + " ret = {\n") - write_c("\t\t.this_arg = (void*) calls,\n") - for fn_line in trait_fn_lines: - if fn_line.group(3) != "free" and fn_line.group(3) != "clone": - write_c("\t\t." + fn_line.group(3) + " = " + fn_line.group(3) + "_jcall,\n") - elif fn_line.group(3) == "free": - write_c("\t\t.free = " + struct_name + "_JCalls_free,\n") - else: - write_c("\t\t.clone = " + struct_name + "_JCalls_clone,\n") - for idx, var_line in enumerate(field_var_lines): - if var_line.group(1) in trait_structs: - write_c("\t\t." + var_line.group(2) + " = " + var_line.group(1) + "_init(env, clz, " + var_line.group(2) + "),\n") - elif field_var_convs[idx].arg_conv_name is not None: - write_c("\t\t." + var_line.group(2) + " = " + field_var_convs[idx].arg_conv_name + ",\n") - write_c("\t\t.set_" + var_line.group(2) + " = NULL,\n") - else: - write_c("\t\t." + var_line.group(2) + " = " + var_line.group(2) + ",\n") - write_c("\t\t.set_" + var_line.group(2) + " = NULL,\n") - write_c("\t};\n") - for var_line in field_var_lines: - if var_line.group(1) in trait_structs: - write_c("\tcalls->" + var_line.group(2) + " = ret." + var_line.group(2) + ".this_arg;\n") - write_c("\treturn ret;\n") - write_c("}\n") - - write_c(consts.c_fn_ty_pfx + "long " + consts.c_fn_name_pfx + struct_name.replace("_", "_1") + "_1new (" + consts.c_fn_args_pfx + ", jobject o") - for idx, var_line in enumerate(field_var_lines): - if var_line.group(1) in trait_structs: - write_c(", jobject " + var_line.group(2)) - else: - write_c(", " + field_var_convs[idx].c_ty + " " + var_line.group(2)) - write_c(") {\n") - write_c("\t" + struct_name + " *res_ptr = MALLOC(sizeof(" + struct_name + "), \"" + struct_name + "\");\n") - write_c("\t*res_ptr = " + struct_name + "_init(env, clz, o") - for var_line in field_var_lines: - write_c(", " + var_line.group(2)) - write_c(");\n") - write_c("\treturn (long)res_ptr;\n") - write_c("}\n") - - out_java.write("\tpublic static native " + struct_name + " " + struct_name + "_get_obj_from_jcalls(long val);\n") - write_c(consts.c_fn_ty_pfx + "jobject " + consts.c_fn_name_pfx + struct_name.replace("_", "_1") + "_1get_1obj_1from_1jcalls (" + consts.c_fn_args_pfx + ", " + consts.ptr_c_ty + " val) {\n") - write_c("\tjobject ret = (*env)->NewLocalRef(env, ((" + struct_name + "_JCalls*)val)->o);\n") - write_c("\tCHECK(ret != NULL);\n") - write_c("\treturn ret;\n") - write_c("}\n") + (out_java_addendum, out_java_trait_addendum, out_c_addendum) = consts.native_c_map_trait(struct_name, field_var_convs, field_fns) + write_c(out_c_addendum) + out_java_trait.write(out_java_trait_addendum) + out_java.write(out_java_addendum) for fn_line in trait_fn_lines: # For now, just disable enabling the _call_log - we don't know how to inverse-map String @@ -1402,7 +1242,7 @@ public class bindings { """) - with open(f"{sys.argv[3]}/structs/CommonBase{consts.file_ext}", "a") as out_java_struct: + with open(f"{sys.argv[3]}/structs/CommonBase{consts.file_ext}", "w") as out_java_struct: out_java_struct.write(consts.common_base) in_block_comment = False