X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=java_strings.py;h=c3e4cb32d9c9d978fdc24ab43a4dc482d8c56ea7;hb=997a742c60ecadf6667779d409e0b35e03521c0d;hp=650e36bf92bbd996e4649a3ce5cacbb289853fc6;hpb=1d4aa806117a28f8a5899ed0dc4e9ad7ed117787;p=ldk-java diff --git a/java_strings.py b/java_strings.py index 650e36bf..c3e4cb32 100644 --- a/java_strings.py +++ b/java_strings.py @@ -5,6 +5,7 @@ import sys class Target(Enum): JAVA = 1, ANDROID = 2 + MACOS = 3 class Consts: def __init__(self, DEBUG: bool, target: Target, **kwargs): @@ -16,6 +17,8 @@ class Consts: uint16_t = ['short'], uint32_t = ['int'], uint64_t = ['long'], + int64_t = ['long'], + double = ['double'], ) self.java_type_map = dict( String = "String" @@ -129,6 +132,38 @@ class CommonBase { } }""" + self.txin_defn = """public class TxIn extends CommonBase { + /** The witness in this input, in serialized form */ + public final byte[] witness; + /** The script_sig in this input */ + public final byte[] script_sig; + /** The transaction output's sequence number */ + public final int sequence; + /** The txid this input is spending */ + public final byte[] previous_txid; + /** The output index within the spent transaction of the output this input is spending */ + public final int previous_vout; + + TxIn(java.lang.Object _dummy, long ptr) { + super(ptr); + this.witness = bindings.TxIn_get_witness(ptr); + this.script_sig = bindings.TxIn_get_script_sig(ptr); + this.sequence = bindings.TxIn_get_sequence(ptr); + this.previous_txid = bindings.TxIn_get_previous_txid(ptr); + this.previous_vout = bindings.TxIn_get_previous_vout(ptr); + } + /** Constructs a new TxIn, note that previous_txid must be exactly 32 bytes */ + public TxIn(byte[] witness, byte[] script_sig, int sequence, byte[] previous_txid, int previous_vout) { + this(null, bindings.TxIn_new(witness, script_sig, sequence, previous_txid, previous_vout)); + } + + @Override @SuppressWarnings(\"deprecation\") + protected void finalize() throws Throwable { + super.finalize(); + if (ptr != 0) { bindings.TxIn_free(ptr); } + } +}""" + self.scalar_defn = """public class BigEndianScalar extends CommonBase { /** The bytes of the scalar value, in big endian */ public final byte[] scalar_bytes; @@ -193,7 +228,7 @@ void __attribute__((constructor)) spawn_stderr_redirection() { else: self.c_file_pfx = self.c_file_pfx + "#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__)\n" - if not DEBUG or sys.platform == "darwin": + if not DEBUG or self.target == Target.MACOS: self.c_file_pfx = self.c_file_pfx + """#define MALLOC(a, _) malloc(a) #define FREE(p) if ((uint64_t)(p) > 4096) { free(p); } #define CHECK_ACCESS(p) @@ -218,7 +253,7 @@ void __attribute__((constructor)) debug_log_version() { } """ - if sys.platform != "darwin": + if self.target != Target.MACOS: self.c_file_pfx += """ // Running a leak check across all the allocations and frees of the JDK is a mess, // so instead we implement our own naive leak checker here, relying on the -wrap @@ -521,6 +556,8 @@ import javax.annotation.Nullable; clz_var = ty_info.java_fn_ty_arg[1:].replace("[", "arr_of_") self.c_array_class_caches.add(clz_var) return "(*env)->NewObjectArray(env, " + arr_len + ", " + clz_var + "_clz, NULL);\n" + elif ty_info.subty.c_ty == "jstring": + return "(*env)->NewObjectArray(env, " + arr_len + ", String_clz, NULL);\n" else: return "(*env)->New" + ty_info.java_ty.strip("[]").title() + "Array(env, " + arr_len + ")" def set_native_arr_contents(self, arr_name, arr_len, ty_info): @@ -531,6 +568,8 @@ import javax.annotation.Nullable; else: assert False def get_native_arr_contents(self, arr_name, dest_name, arr_len, ty_info, copy): + if "String" in ty_info.java_ty: + return None if ty_info.c_ty == "int8_tArray" or ty_info.c_ty == "int16_tArray": fn_ty = "Byte" if ty_info.c_ty == "int8_tArray" else "Short" if copy: @@ -590,11 +629,16 @@ import javax.annotation.Nullable; res = "" for ty in sorted(self.c_array_class_caches): res = res + "static jclass " + ty + "_clz = NULL;\n" + res = res + "static jclass String_clz = NULL;\n" res = res + "JNIEXPORT void Java_org_ldk_impl_bindings_init_1class_1cache(JNIEnv * env, jclass clz) {\n" for ty in sorted(self.c_array_class_caches): res = res + "\t" + ty + "_clz = (*env)->FindClass(env, \"" + ty.replace("arr_of_", "[") + "\");\n" res = res + "\tCHECK(" + ty + "_clz != NULL);\n" res = res + "\t" + ty + "_clz = (*env)->NewGlobalRef(env, " + ty + "_clz);\n" + res = res + "\tString_clz = (*env)->FindClass(env, \"java/lang/String\");\n" + res = res + "\tCHECK(String_clz != NULL);\n" + res = res + "\tString_clz = (*env)->NewGlobalRef(env, String_clz);\n" + res = res + "}\n" return res @@ -777,12 +821,26 @@ import javax.annotation.Nullable; out_java_trait = out_java_trait + "\t\t" + var.from_hu_conv[1].replace("\n", "\n\t\t") + ";\n" else: out_java_trait = out_java_trait + "\t\tthis.ptrs_to.add(" + var[1] + ");\n" - out_java_trait = out_java_trait + "\t\tthis.bindings_instance = arg;\n" - out_java_trait = out_java_trait + "\t}\n" - out_java_trait = out_java_trait + "\t@Override @SuppressWarnings(\"deprecation\")\n" - out_java_trait = out_java_trait + "\tprotected void finalize() throws Throwable {\n" - out_java_trait = out_java_trait + "\t\tif (ptr != 0) { bindings." + struct_name.replace("LDK","") + "_free(ptr); } super.finalize();\n" - out_java_trait = out_java_trait + "\t}\n\n" + out_java_trait += f""" this.bindings_instance = arg; + }} + @Override @SuppressWarnings("deprecation") + protected void finalize() throws Throwable {{ + if (ptr != 0) {{ bindings.{struct_name.replace("LDK","")}_free(ptr); }} super.finalize(); + }} + /** + * Destroys the object, freeing associated resources. After this call, any access + * to this object may result in a SEGFAULT or worse. + * + * You should generally NEVER call this method. You should let the garbage collector + * do this for you when it finalizes objects. However, it may be useful for types + * which represent locks and should be closed immediately to avoid holding locks + * until the GC runs. + */ + public void destroy() {{ + if (ptr != 0) {{ bindings.{struct_name.replace("LDK","")}_free(ptr); }} + ptr = 0; + }} +""" 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" @@ -857,17 +915,21 @@ import javax.annotation.Nullable; java_trait_constr = java_trait_constr + ", " + var.arg_name else: java_trait_constr += ", " + var[1] + ".new_impl(" + var[1] + "_impl" + suptrait_constr = "" for suparg in var[2]: if isinstance(suparg, ConvInfo): - java_trait_constr += ", " + suparg.arg_name + suptrait_constr += ", " + suparg.arg_name else: - java_trait_constr += ", " + suparg[1] - java_trait_constr += ").bindings_instance" + suptrait_constr += ", " + suparg[1] + "_impl" + java_trait_constr += suptrait_constr + ").bindings_instance" for suparg in var[2]: if isinstance(suparg, ConvInfo): java_trait_constr += ", " + suparg.arg_name else: - java_trait_constr += ", " + suparg[1] + java_trait_constr += ", " + suparg[1] + ".new_impl(" + # Blindly assume that we can just strip the first arg to build the args for the supertrait + java_trait_constr += suptrait_constr.split(", ", 1)[1] + java_trait_constr += ").bindings_instance" out_java_trait = out_java_trait + "\t}\n" out_java_trait = out_java_trait + java_trait_constr + ");\n\t\treturn impl_holder.held;\n\t}\n" @@ -976,9 +1038,9 @@ import javax.annotation.Nullable; out_c = out_c + "static void " + struct_name + "_JCalls_cloned(" + struct_name + "* new_obj) {\n" out_c = out_c + "\t" + struct_name + "_JCalls *j_calls = (" + struct_name + "_JCalls*) new_obj->this_arg;\n" out_c = out_c + "\tatomic_fetch_add_explicit(&j_calls->refcnt, 1, memory_order_release);\n" - for var in field_vars: + for var in flattened_field_vars: if not isinstance(var, ConvInfo): - out_c = out_c + "\tatomic_fetch_add_explicit(&j_calls->" + var[1] + "->refcnt, 1, memory_order_release);\n" + out_c = out_c + "\tatomic_fetch_add_explicit(&j_calls->" + var[2].replace(".", "->") + "->refcnt, 1, memory_order_release);\n" out_c = out_c + "}\n" out_c = out_c + "static inline " + struct_name + " " + struct_name + "_init (" + self.c_fn_args_pfx + ", jobject o" @@ -1032,7 +1094,7 @@ import javax.annotation.Nullable; out_c = out_c + "\t};\n" for var in flattened_field_vars: if not isinstance(var, ConvInfo): - out_c = out_c + "\tcalls->" + var[1] + " = ret." + var[1] + ".this_arg;\n" + out_c = out_c + "\tcalls->" + var[1] + " = ret." + var[2] + ".this_arg;\n" out_c = out_c + "\treturn ret;\n" out_c = out_c + "}\n" @@ -1062,7 +1124,7 @@ import javax.annotation.Nullable; underscore_name = ''.join('_' + c.lower() if c.isupper() else c for c in var[1]).strip('_') out_java_trait += "\tpublic " + var[1] + " get_" + underscore_name + "() {\n" out_java_trait += "\t\t" + var[1] + " res = new " + var[1] + "(null, bindings." + struct_name + "_get_" + var[1] + "(this.ptr));\n" - out_java_trait += "\t\tthis.ptrs_to.add(res);\n" + out_java_trait += "\t\tres.ptrs_to.add(this);\n" out_java_trait += "\t\treturn res;\n" out_java_trait += "\t}\n" out_java_trait += "\n" @@ -1071,7 +1133,7 @@ import javax.annotation.Nullable; out_c += "JNIEXPORT int64_t JNICALL Java_org_ldk_impl_bindings_" + struct_name + "_1get_1" + var[1] + "(JNIEnv *env, jclass clz, int64_t arg) {\n" out_c += "\t" + struct_name + " *inp = (" + struct_name + " *)untag_ptr(arg);\n" - out_c += "\treturn tag_ptr(&inp->" + var[1] + ", false);\n" + out_c += "\treturn tag_ptr(&inp->" + var[2] + ", false);\n" out_c += "}\n" return (out_java, out_java_trait, out_c) @@ -1313,6 +1375,8 @@ import javax.annotation.Nullable; extra_java_struct_out += "\t\tif (!(o instanceof " + struct_meth + ")) return false;\n" extra_java_struct_out += "\t\treturn this.eq((" + struct_meth + ")o);\n" extra_java_struct_out += "\t}\n" + if meth_n == "wait": + meth_n = "wait_indefinite" out_java_struct += ("\tpublic " + return_type_info.java_hu_ty + " " + meth_n + "(") for idx, arg in enumerate(argument_types): if idx != 0: