X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=genbindings.py;h=1ed228a56eb6b8f2e4192ff35d44e65e8240321b;hb=196f002e1d9016295c51b37b16986068ecf8db3e;hp=453e5c0320887f4edf7c8a236d9fee29aa8c4222;hpb=5e83938c7ad3dbb386453875fa63c1a56c78635d;p=ldk-java diff --git a/genbindings.py b/genbindings.py index 453e5c03..1ed228a5 100755 --- a/genbindings.py +++ b/genbindings.py @@ -115,13 +115,14 @@ void* __wrap_calloc(size_t nmemb, size_t len) { return res; } void __wrap_free(void* ptr) { + if (ptr == NULL) return; alloc_freed(ptr); __real_free(ptr); } void* __real_realloc(void* ptr, size_t newlen); void* __wrap_realloc(void* ptr, size_t len) { - alloc_freed(ptr); + if (ptr != NULL) alloc_freed(ptr); void* res = __real_realloc(ptr, len); new_allocation(res, "realloc call"); return res; @@ -161,6 +162,7 @@ class TypeInfo: self.arr_access = arr_access self.subty = subty self.pass_by_ref = is_ptr + self.requires_clone = None class ConvInfo: def __init__(self, ty_info, arg_name, arg_conv, arg_conv_name, arg_conv_cleanup, ret_conv, ret_conv_name, to_hu_conv, to_hu_conv_name, from_hu_conv): @@ -228,9 +230,6 @@ trait_structs = set() result_types = set() tuple_types = {} -def is_common_base_ext(struct_name): - return struct_name in complex_enums or struct_name in opaque_structs or struct_name in trait_structs or struct_name in result_types - 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 @@ -303,6 +302,11 @@ def java_c_types(fn_arg, ret_arr_len): rust_obj = "LDKCVec_u8Z" assert var_is_arr_regex.match(fn_arg[8:]) arr_access = "data" + elif fn_arg.startswith("LDKTransaction"): + fn_arg = "uint8_t (*" + fn_arg[15:] + ")[datalen]" + rust_obj = "LDKTransaction" + assert var_is_arr_regex.match(fn_arg[8:]) + arr_access = "data" elif fn_arg.startswith("LDKCVecTempl_") or fn_arg.startswith("LDKCVec_"): is_ptr = False if "*" in fn_arg: @@ -518,14 +522,20 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: arg_conv_cleanup = None if not arr_len.isdigit(): arg_conv = ty_info.rust_obj + " " + arr_name + "_ref;\n" - arg_conv = arg_conv + arr_name + "_ref." + ty_info.arr_access + " = (*_env)->GetByteArrayElements (_env, " + arr_name + ", NULL);\n" - arg_conv = arg_conv + arr_name + "_ref." + arr_len + " = (*_env)->GetArrayLength (_env, " + arr_name + ");" - arg_conv_cleanup = "(*_env)->ReleaseByteArrayElements(_env, " + arr_name + ", (int8_t*)" + arr_name + "_ref." + ty_info.arr_access + ", 0);" + arg_conv = arg_conv + arr_name + "_ref." + arr_len + " = (*_env)->GetArrayLength (_env, " + arr_name + ");\n" + if (not ty_info.is_ptr or not holds_ref) and ty_info.rust_obj != "LDKu8slice": + arg_conv = arg_conv + arr_name + "_ref." + ty_info.arr_access + " = MALLOC(" + arr_name + "_ref." + arr_len + ", \"" + ty_info.rust_obj + " Bytes\");\n" + arg_conv = arg_conv + "(*_env)->GetByteArrayRegion(_env, " + arr_name + ", 0, " + arr_name + "_ref." + arr_len + ", " + arr_name + "_ref." + ty_info.arr_access + ");" + else: + arg_conv = arg_conv + arr_name + "_ref." + ty_info.arr_access + " = (*_env)->GetByteArrayElements (_env, " + arr_name + ", NULL);" + arg_conv_cleanup = "(*_env)->ReleaseByteArrayElements(_env, " + arr_name + ", (int8_t*)" + arr_name + "_ref." + ty_info.arr_access + ", 0);" + if ty_info.rust_obj == "LDKTransaction": + arg_conv = arg_conv + "\n" + arr_name + "_ref.data_is_owned = " + str(holds_ref).lower() + ";" ret_conv = (ty_info.rust_obj + " " + arr_name + "_var = ", "") ret_conv = (ret_conv[0], ";\njbyteArray " + arr_name + "_arr = (*_env)->NewByteArray(_env, " + arr_name + "_var." + arr_len + ");\n") ret_conv = (ret_conv[0], ret_conv[1] + "(*_env)->SetByteArrayRegion(_env, " + arr_name + "_arr, 0, " + arr_name + "_var." + arr_len + ", " + arr_name + "_var." + ty_info.arr_access + ");") - if not holds_ref and ty_info.rust_obj == "LDKCVec_u8Z": - ret_conv = (ret_conv[0], ret_conv[1] + "\nCVec_u8Z_free(" + arr_name + "_var);") + if not holds_ref and ty_info.rust_obj != "LDKu8slice": + ret_conv = (ret_conv[0], ret_conv[1] + "\n" + ty_info.rust_obj.replace("LDK", "") + "_free(" + arr_name + "_var);") elif ty_info.rust_obj is not None: arg_conv = ty_info.rust_obj + " " + arr_name + "_ref;\n" arg_conv = arg_conv + "CHECK((*_env)->GetArrayLength (_env, " + arr_name + ") == " + arr_len + ");\n" @@ -545,7 +555,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: conv_name = "arr_conv_" + str(len(ty_info.java_hu_ty)) idxc = chr(ord('a') + (len(ty_info.java_hu_ty) % 26)) ty_info.subty.var_name = conv_name - ty_info.subty.passed_as_ptr = False + ty_info.subty.requires_clone = not ty_info.is_ptr or not holds_ref subty = map_type_with_info(ty_info.subty, False, None, is_free, holds_ref) if arr_name == "": arr_name = "arg" @@ -666,19 +676,56 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: else: if ty_info.var_name == "": ty_info.var_name = "ret" - opaque_arg_conv = ty_info.rust_obj + " " + ty_info.var_name + "_conv;\n" - opaque_arg_conv = opaque_arg_conv + ty_info.var_name + "_conv.inner = (void*)(" + ty_info.var_name + " & (~1));\n" - if holds_ref: - opaque_arg_conv = opaque_arg_conv + ty_info.var_name + "_conv.is_owned = false;" - else: - opaque_arg_conv = opaque_arg_conv + ty_info.var_name + "_conv.is_owned = (" + ty_info.var_name + " & 1) || (" + ty_info.var_name + " == 0);" - if not ty_info.is_ptr and not is_free and not ty_info.pass_by_ref and not holds_ref: - if (ty_info.java_hu_ty + "_clone") in clone_fns: - # TODO: This is a bit too naive, even with the checks above, we really need to know if rust wants a ref or not, not just if its pass as a ptr. - opaque_arg_conv = opaque_arg_conv + "\nif (" + ty_info.var_name + "_conv.inner != NULL)\n" - opaque_arg_conv = opaque_arg_conv + "\t" + ty_info.var_name + "_conv = " + ty_info.java_hu_ty + "_clone(&" + ty_info.var_name + "_conv);" - elif ty_info.passed_as_ptr: - opaque_arg_conv = opaque_arg_conv + "\n// Warning: we may need a move here but can't clone!" + + if ty_info.rust_obj in opaque_structs: + opaque_arg_conv = ty_info.rust_obj + " " + ty_info.var_name + "_conv;\n" + opaque_arg_conv = opaque_arg_conv + ty_info.var_name + "_conv.inner = (void*)(" + ty_info.var_name + " & (~1));\n" + if ty_info.is_ptr and holds_ref: + opaque_arg_conv = opaque_arg_conv + ty_info.var_name + "_conv.is_owned = false;" + else: + opaque_arg_conv = opaque_arg_conv + ty_info.var_name + "_conv.is_owned = (" + ty_info.var_name + " & 1) || (" + ty_info.var_name + " == 0);" + if not is_free and (not ty_info.is_ptr or not holds_ref or ty_info.requires_clone == True) and ty_info.requires_clone != False: + if (ty_info.java_hu_ty + "_clone") in clone_fns: + # TODO: This is a bit too naive, even with the checks above, we really need to know if rust wants a ref or not, not just if its pass as a ptr. + opaque_arg_conv = opaque_arg_conv + "\nif (" + ty_info.var_name + "_conv.inner != NULL)\n" + opaque_arg_conv = opaque_arg_conv + "\t" + ty_info.var_name + "_conv = " + ty_info.java_hu_ty + "_clone(&" + ty_info.var_name + "_conv);" + elif ty_info.passed_as_ptr: + opaque_arg_conv = opaque_arg_conv + "\n// Warning: we may need a move here but can't clone!" + + opaque_ret_conv_suf = ";\n" + if not holds_ref and ty_info.is_ptr and (ty_info.java_hu_ty + "_clone") in clone_fns: # is_ptr, not holds_ref implies passing a pointed-to value to java, which needs copied + opaque_ret_conv_suf = opaque_ret_conv_suf + "if (" + ty_info.var_name + "->inner != NULL)\n" + opaque_ret_conv_suf = opaque_ret_conv_suf + "\t" + ty_info.var_name + "_var = " + ty_info.java_hu_ty + "_clone(" + ty_info.var_name + ");\n" + elif not holds_ref and ty_info.is_ptr: + opaque_ret_conv_suf = opaque_ret_conv_suf + "// Warning: we may need a move here but can't clone!\n" + + opaque_ret_conv_suf = opaque_ret_conv_suf + "CHECK((((long)" + ty_info.var_name + "_var.inner) & 1) == 0); // We rely on a free low bit, malloc guarantees this.\n" + opaque_ret_conv_suf = opaque_ret_conv_suf + "CHECK((((long)&" + ty_info.var_name + "_var) & 1) == 0); // We rely on a free low bit, pointer alignment guarantees this.\n" + if holds_ref: + opaque_ret_conv_suf = opaque_ret_conv_suf + "long " + ty_info.var_name + "_ref = (long)" + ty_info.var_name + "_var.inner & ~1;" + else: + opaque_ret_conv_suf = opaque_ret_conv_suf + "long " + ty_info.var_name + "_ref = (long)" + ty_info.var_name + "_var.inner;\n" + opaque_ret_conv_suf = opaque_ret_conv_suf + "if (" + ty_info.var_name + "_var.is_owned) {\n" + opaque_ret_conv_suf = opaque_ret_conv_suf + "\t" + ty_info.var_name + "_ref |= 1;\n" + opaque_ret_conv_suf = opaque_ret_conv_suf + "}" + + 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 = 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_name = ty_info.var_name + "_hu_conv", + from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr & ~1", "this.ptrs_to.add(" + ty_info.var_name + ")")) + else: + 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 = 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_name = ty_info.var_name + "_hu_conv", + from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr & ~1", "this.ptrs_to.add(" + ty_info.var_name + ")")) + if not ty_info.is_ptr: if ty_info.rust_obj in unitary_enums: return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, @@ -687,39 +734,29 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: arg_conv_cleanup = None, ret_conv = ("jclass " + ty_info.var_name + "_conv = " + ty_info.rust_obj + "_to_java(_env, ", ");"), ret_conv_name = ty_info.var_name + "_conv", to_hu_conv = None, to_hu_conv_name = None, from_hu_conv = None) - if ty_info.rust_obj in opaque_structs: - ret_conv_suf = ";\nCHECK((((long)" + ty_info.var_name + "_var.inner) & 1) == 0); // We rely on a free low bit, malloc guarantees this.\n" - ret_conv_suf = ret_conv_suf + "CHECK((((long)&" + ty_info.var_name + "_var) & 1) == 0); // We rely on a free low bit, pointer alignment guarantees this.\n" - if holds_ref: - ret_conv_suf = ret_conv_suf + "long " + ty_info.var_name + "_ref = (long)" + ty_info.var_name + "_var.inner & ~1;" - else: - ret_conv_suf = ret_conv_suf + "long " + ty_info.var_name + "_ref = (long)" + ty_info.var_name + "_var.inner;\n" - ret_conv_suf = ret_conv_suf + "if (" + ty_info.var_name + "_var.is_owned) {\n" - ret_conv_suf = ret_conv_suf + "\t" + ty_info.var_name + "_ref |= 1;\n" - ret_conv_suf = ret_conv_suf + "}" - 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 = ", ret_conv_suf), - ret_conv_name = ty_info.var_name + "_ref", - 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_name = ty_info.var_name + "_hu_conv", - from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr & ~1", "this.ptrs_to.add(" + ty_info.var_name + ")")) - base_conv = ty_info.rust_obj + " " + ty_info.var_name + "_conv = *(" + ty_info.rust_obj + "*)" + ty_info.var_name + ";"; + base_conv = ty_info.rust_obj + " " + ty_info.var_name + "_conv = *(" + ty_info.rust_obj + "*)" + ty_info.var_name + ";" if ty_info.rust_obj in trait_structs: if not is_free: - base_conv = base_conv + "\nif (" + ty_info.var_name + "_conv.free == " + ty_info.rust_obj + "_JCalls_free) {\n" - base_conv = base_conv + "\t// If this_arg is a JCalls struct, then we need to increment the refcnt in it.\n" - base_conv = base_conv + "\t" + ty_info.rust_obj + "_JCalls_clone(" + ty_info.var_name + "_conv.this_arg);\n}" + needs_full_clone = not is_free and (not ty_info.is_ptr and not holds_ref or ty_info.requires_clone == True) and ty_info.requires_clone != False + if needs_full_clone and (ty_info.java_hu_ty + "_clone") in clone_fns: + base_conv = base_conv + "\n" + ty_info.var_name + "_conv = " + ty_info.java_hu_ty + "_clone(" + ty_info.var_name + ");" + else: + base_conv = base_conv + "\nif (" + ty_info.var_name + "_conv.free == " + ty_info.rust_obj + "_JCalls_free) {\n" + base_conv = base_conv + "\t// If this_arg is a JCalls struct, then we need to increment the refcnt in it.\n" + base_conv = base_conv + "\t" + ty_info.rust_obj + "_JCalls_clone(" + ty_info.var_name + "_conv.this_arg);\n}" + if needs_full_clone: + base_conv = base_conv + "// Warning: we may need a move here but can't do a full clone!\n" + else: base_conv = base_conv + "\n" + "FREE((void*)" + ty_info.var_name + ");" 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 = (ty_info.rust_obj + "* ret = MALLOC(sizeof(" + ty_info.rust_obj + "), \"" + ty_info.rust_obj + "\");\n*ret = ", ";"), ret_conv_name = "(long)ret", - to_hu_conv = ty_info.java_hu_ty + " ret_hu_conv = new " + ty_info.java_hu_ty + "(null, ret);\nret_hu_conv.ptrs_to.add(this);", + to_hu_conv = ty_info.java_hu_ty + " ret_hu_conv = new " + ty_info.java_hu_ty + "(null, " + ty_info.var_name + ");\nret_hu_conv.ptrs_to.add(this);", to_hu_conv_name = "ret_hu_conv", from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr", "this.ptrs_to.add(" + ty_info.var_name + ")")) - if ty_info.rust_obj != "LDKu8slice" and ty_info.rust_obj != "LDKTransaction": + if ty_info.rust_obj != "LDKu8slice": # Don't bother free'ing slices passed in - Rust doesn't auto-free the # underlying unlike Vecs, and it gives Java more freedom. base_conv = base_conv + "\nFREE((void*)" + ty_info.var_name + ");"; @@ -727,8 +764,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: ret_conv = ("long " + ty_info.var_name + "_ref = (long)&", ";") if not holds_ref: ret_conv = (ty_info.rust_obj + " *" + ty_info.var_name + "_copy = MALLOC(sizeof(" + ty_info.rust_obj + "), \"" + ty_info.rust_obj + "\");\n", "") - if not ty_info.passed_as_ptr: - # We use passed_as_ptr as a flag to detect if we're copying a Vec. + if ty_info.requires_clone == True: # Set in object array mapping if (ty_info.java_hu_ty + "_clone") in clone_fns: ret_conv = (ret_conv[0] + "*" + ty_info.var_name + "_copy = " + ty_info.java_hu_ty + "_clone(&", ");\n") else: @@ -785,30 +821,15 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: to_hu_conv = to_hu_conv_pfx + to_hu_conv_sfx + ");", to_hu_conv_name = ty_info.var_name + "_conv", from_hu_conv = (from_hu_conv + ")", "")) # The manually-defined types - TxOut and Transaction - assert ty_info.rust_obj == "LDKTransaction" or ty_info.rust_obj == "LDKTxOut" - if ty_info.rust_obj == "LDKTransaction": - 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 = ("LDKTransaction *" + ty_info.var_name + "_copy = MALLOC(sizeof(LDKTransaction), \"LDKTransaction\");\n*" + ty_info.var_name + "_copy = ", ";\nlong " + ty_info.var_name + "_ref = (long)" + ty_info.var_name + "_copy;"), - ret_conv_name = ty_info.var_name + "_ref", - to_hu_conv = ty_info.java_hu_ty + " " + ty_info.var_name + "_conv = new " +ty_info.java_hu_ty + "(null, " + ty_info.var_name + ");", - to_hu_conv_name = ty_info.var_name + "_conv", from_hu_conv = (ty_info.var_name + ".ptr", "")) - elif ty_info.rust_obj == "LDKTxOut": - 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 = ("long " + ty_info.var_name + "_ref = (long)&", ";"), ret_conv_name = ty_info.var_name + "_ref", - to_hu_conv = ty_info.java_hu_ty + " " + ty_info.var_name + "_conv = new " +ty_info.java_hu_ty + "(null, " + ty_info.var_name + ");", - to_hu_conv_name = ty_info.var_name + "_conv", from_hu_conv = (ty_info.var_name + ".ptr", "")) + assert ty_info.rust_obj == "LDKTxOut" + 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 = ("long " + ty_info.var_name + "_ref = (long)&", ";"), ret_conv_name = ty_info.var_name + "_ref", + to_hu_conv = ty_info.java_hu_ty + " " + ty_info.var_name + "_conv = new " +ty_info.java_hu_ty + "(null, " + ty_info.var_name + ");", + to_hu_conv_name = ty_info.var_name + "_conv", from_hu_conv = (ty_info.var_name + ".ptr", "")) elif ty_info.is_ptr: assert(not is_free) - if ty_info.rust_obj in opaque_structs: - 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 = ("long ret_" + ty_info.var_name + " = (long)", ";"), ret_conv_name = "ret_" + ty_info.var_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_name = ty_info.var_name + "_hu_conv", - from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr & ~1", "this.ptrs_to.add(" + ty_info.var_name + ")")) - elif ty_info.rust_obj in complex_enums: + if ty_info.rust_obj in complex_enums: return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = ty_info.rust_obj + "* " + ty_info.var_name + "_conv = (" + ty_info.rust_obj + "*)" + ty_info.var_name + ";", arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, @@ -817,13 +838,24 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: to_hu_conv_name = ty_info.var_name + "_hu_conv", from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr & ~1", "this.ptrs_to.add(" + ty_info.var_name + ")")) elif ty_info.rust_obj in trait_structs: - return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, - arg_conv = ty_info.rust_obj + "* " + ty_info.var_name + "_conv = (" + ty_info.rust_obj + "*)" + ty_info.var_name + ";", - arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, - ret_conv = ("long ret_" + ty_info.var_name + " = (long)", ";"), ret_conv_name = "ret_" + ty_info.var_name, - to_hu_conv = ty_info.java_hu_ty + " ret_hu_conv = new " + ty_info.java_hu_ty + "(null, ret);\nret_hu_conv.ptrs_to.add(this);", - to_hu_conv_name = "ret_hu_conv", - from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr", "this.ptrs_to.add(" + ty_info.var_name + ")")) + if ty_info.java_hu_ty + "_clone" in clone_fns: + return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, + arg_conv = ty_info.rust_obj + "* " + ty_info.var_name + "_conv = (" + ty_info.rust_obj + "*)" + ty_info.var_name + ";", + arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, + ret_conv = (ty_info.rust_obj + " *" + ty_info.var_name + "_clone = MALLOC(sizeof(" + ty_info.rust_obj + "), \"" + ty_info.rust_obj + "\");\n" + + "*" + ty_info.var_name + "_clone = " + ty_info.java_hu_ty + "_clone(", ");"), + ret_conv_name = "(long)" + ty_info.var_name + "_clone", + to_hu_conv = ty_info.java_hu_ty + " ret_hu_conv = new " + ty_info.java_hu_ty + "(null, " + ty_info.var_name + ");\nret_hu_conv.ptrs_to.add(this);", + to_hu_conv_name = "ret_hu_conv", + from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr", "this.ptrs_to.add(" + ty_info.var_name + ")")) + else: + return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, + arg_conv = ty_info.rust_obj + "* " + ty_info.var_name + "_conv = (" + ty_info.rust_obj + "*)" + ty_info.var_name + ";", + arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, + ret_conv = ("long ret_" + ty_info.var_name + " = (long)", ";"), ret_conv_name = "ret_" + ty_info.var_name, + to_hu_conv = ty_info.java_hu_ty + " ret_hu_conv = new " + ty_info.java_hu_ty + "(null, " + ty_info.var_name + ");\nret_hu_conv.ptrs_to.add(this);", + to_hu_conv_name = "ret_hu_conv", + from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr", "this.ptrs_to.add(" + ty_info.var_name + ")")) return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = ty_info.rust_obj + "* " + ty_info.var_name + "_conv = (" + ty_info.rust_obj + "*)" + ty_info.var_name + ";", arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, @@ -857,7 +889,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: out_java.write(", ") if arg != "void": write_c(", ") - arg_conv_info = map_type(arg, False, None, is_free, False) + arg_conv_info = map_type(arg, False, None, is_free, True) if arg_conv_info.c_ty != "void": arg_conv_info.print_ty() arg_conv_info.print_name() @@ -867,7 +899,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: if arg_conv_info.rust_obj in constructor_fns: assert not is_free for explode_arg in constructor_fns[arg_conv_info.rust_obj].split(','): - explode_arg_conv = map_type(explode_arg, False, None, False, False) + explode_arg_conv = 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. @@ -975,7 +1007,10 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: out_java_struct.write(info.arg_name) out_java_struct.write(");\n") if ret_info.to_hu_conv is not None: - out_java_struct.write("\t\t" + ret_info.to_hu_conv.replace("\n", "\n\t\t") + "\n") + if ret_info.rust_obj == "LDK" + struct_meth: + out_java_struct.write("\t\t" + ret_info.to_hu_conv.replace("\n", "\n\t\t").replace("this", ret_info.to_hu_conv_name) + "\n") + else: + out_java_struct.write("\t\t" + ret_info.to_hu_conv.replace("\n", "\n\t\t") + "\n") for info in arg_names: if info.arg_name == "this_ptr" or info.arg_name == "this_arg": @@ -1211,15 +1246,17 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: 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 = "\tpublic " + struct_name.replace("LDK", "") + "(" + struct_name.replace("LDK", "") + "Interface arg" + 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) + 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\tthis(new bindings." + struct_name + "() {\n" + 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 = [] @@ -1306,8 +1343,9 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: 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//TODO: May need to call: " + ret_ty_info.from_hu_conv[1] + ";\n" - if is_common_base_ext(ret_ty_info.rust_obj): + 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: @@ -1325,11 +1363,11 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: 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 + ", new " + var_line.group(2) + "(" + var_line.group(2) + ").bindings_instance" + 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}\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") @@ -1376,7 +1414,6 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: elif fn_line.group(2) == "free": write_c("\t\t.free = " + struct_name + "_JCalls_free,\n") else: - clone_fns.add(struct_name + "_clone") 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: @@ -1777,16 +1814,6 @@ class CommonBase { out_java_struct.write("\tlong to_c_ptr() { return 0; }\n") # TODO: TxOut body out_java_struct.write("}") - elif struct_name == "LDKTransaction": - with open(sys.argv[3] + "/structs/Transaction.java", "w") as out_java_struct: - out_java_struct.write(hu_struct_file_prefix) - out_java_struct.write("public class Transaction extends CommonBase{\n") - out_java_struct.write("\tTransaction(java.lang.Object _dummy, long ptr) { super(ptr); }\n") - out_java_struct.write("\tpublic Transaction(byte[] data) { super(bindings.new_txpointer_copy_data(data)); }\n") - out_java_struct.write("\t@Override public void finalize() throws Throwable { super.finalize(); bindings.txpointer_free(ptr); }\n") - out_java_struct.write("\tpublic byte[] get_contents() { return bindings.txpointer_get_buffer(ptr); }\n") - # TODO: Transaction body - out_java_struct.write("}") else: pass # Everything remaining is a byte[] or some form cur_block_obj = None