uint32_t = ['int'],
uint64_t = ['long'],
)
+ self.java_type_map = dict(
+ String = "String"
+ )
+ self.java_hu_type_map = dict(
+ String = "String"
+ )
self.to_hu_conv_templates = dict(
ptr = '{human_type} {var_name}_hu_conv = null; if ({var_name} < 0 || {var_name} > 4096) { {var_name}_hu_conv = new {human_type}(null, {var_name}); }',
}
}"""
+ self.scalar_defn = """public class BigEndianScalar extends CommonBase {
+ /** The bytes of the scalar value, in big endian */
+ public final byte[] scalar_bytes;
+
+ BigEndianScalar(java.lang.Object _dummy, long ptr) {
+ super(ptr);
+ this.scalar_bytes = bindings.BigEndianScalar_get_bytes(ptr);
+ }
+ public BigEndianScalar(byte[] scalar_bytes) {
+ super(bindings.BigEndianScalar_new(scalar_bytes));
+ this.scalar_bytes = bindings.BigEndianScalar_get_bytes(ptr);
+ }
+
+ @Override @SuppressWarnings(\"deprecation\")
+ protected void finalize() throws Throwable {
+ super.finalize();
+ if (ptr != 0) { bindings.BigEndianScalar_free(ptr); }
+ }
+}"""
+
+
self.c_file_pfx = """#include <jni.h>
// On OSX jlong (ie long long) is not equivalent to int64_t, so we override here
#define int64_t jlong
self.file_ext = ".java"
self.ptr_c_ty = "int64_t"
self.ptr_native_ty = "long"
+ self.usize_c_ty = "int64_t"
+ self.usize_native_ty = "long"
+ self.native_zero_ptr = "0"
self.result_c_ty = "jclass"
self.ptr_arr = "jobjectArray"
self.is_arr_some_check = ("", " != NULL")
return arr_name + " != null ? Arrays.stream(" + arr_name + ").mapToLong(" + conv_name + " -> " + elem_ty.from_hu_conv[0] + ").toArray() : null"
elif elem_ty.java_ty == "long":
return arr_name + " != null ? Arrays.stream(" + arr_name + ").map(" + conv_name + " -> " + elem_ty.from_hu_conv[0] + ").toArray() : null"
+ elif elem_ty.java_hu_ty == "UInt5":
+ return arr_name + " != null ? InternalUtils.convUInt5Array(" + arr_name + ") : null"
+ elif elem_ty.java_hu_ty == "WitnessVersion":
+ return arr_name + " != null ? InternalUtils.convWitnessVersionArray(" + arr_name + ") : null"
else:
return arr_name + " != null ? Arrays.stream(" + arr_name + ").map(" + conv_name + " -> " + elem_ty.from_hu_conv[0] + ").toArray(" + arr_ty.java_ty + "::new) : null"
return "str_ref_to_java(env, " + var_name + ", " + str_len + ")"
def str_ref_to_c_call(self, var_name):
return "java_to_owned_str(env, " + var_name + ")"
+ def str_to_hu_conv(self, var_name):
+ return None
+ def str_from_hu_conv(self, var_name):
+ return None
def c_fn_name_define_pfx(self, fn_name, has_args):
if has_args:
def var_decl_statement(self, ty_string, var_name, statement):
return ty_string + " " + var_name + " = " + statement
+ def get_java_arr_len(self, arr_name):
+ return arr_name + ".length"
+ def get_java_arr_elem(self, elem_ty, arr_name, idx):
+ return arr_name + "[" + idx + "]"
+ def constr_hu_array(self, ty_info, arr_len):
+ base_ty = ty_info.subty.java_hu_ty.split("[")[0].split("<")[0]
+ conv = "new " + base_ty + "[" + arr_len + "]"
+ if "[" in ty_info.subty.java_hu_ty.split("<")[0]:
+ # Do a bit of a dance to move any excess [] to the end
+ conv += "[" + ty_info.subty.java_hu_ty.split("<")[0].split("[")[1]
+ return conv
+ def cleanup_converted_native_array(self, ty_info, arr_name):
+ return None
+
+ def primitive_arr_from_hu(self, mapped_ty, fixed_len, arr_name):
+ if fixed_len is not None:
+ return ("InternalUtils.check_arr_len(" + arr_name + ", " + fixed_len + ")", "")
+ return None
+ def primitive_arr_to_hu(self, primitive_ty, fixed_len, arr_name, conv_name):
+ return None
+
+ def java_arr_ty_str(self, elem_ty_str):
+ return elem_ty_str + "[]"
+
def for_n_in_range(self, n, minimum, maximum):
return "for (int " + n + " = " + minimum + "; " + n + " < " + maximum + "; " + n + "++) {"
def for_n_in_arr(self, n, arr_name, arr_elem_ty):
return var + ".ptr" + " = 0;"
def add_ref(self, holder, referent):
- return holder + ".ptrs_to.add(" + referent + ")"
+ return "if (" + holder + " != null) { " + holder + ".ptrs_to.add(" + referent + "); }"
+
+ def fully_qualified_hu_ty_path(self, ty):
+ if ty.java_fn_ty_arg.startswith("L") and ty.java_fn_ty_arg.endswith(";"):
+ return ty.java_fn_ty_arg.strip("L;").replace("/", ".")
+ if ty.java_hu_ty == "UnqualifiedError" or ty.java_hu_ty == "UInt5" or ty.java_hu_ty == "WitnessVersion":
+ return "org.ldk.util." + ty.java_hu_ty
+ if not ty.is_native_primitive and ty.rust_obj is not None and not "[]" in ty.java_hu_ty:
+ return "org.ldk.structs." + ty.java_hu_ty
+ return ty.java_hu_ty
def native_c_unitary_enum_map(self, struct_name, variants, enum_doc_comment):
out_java_enum = "package org.ldk.enums;\n\n"
else:
java_trait_constr = java_trait_constr + arg_info.arg_name
- java_trait_constr = java_trait_constr + ");\n"
+ java_trait_constr += ");\n"
+ java_trait_constr += "\t\t\t\tReference.reachabilityFence(arg);\n"
if fn_line.ret_ty_info.java_ty != "void":
if fn_line.ret_ty_info.from_hu_conv is not None:
java_trait_constr = java_trait_constr + "\t\t\t\t" + fn_line.ret_ty_info.java_ty + " result = " + fn_line.ret_ty_info.from_hu_conv[0] + ";\n"
if fn_line.ret_ty_info.c_ty.endswith("Array"):
out_c = out_c + "\t" + fn_line.ret_ty_info.c_ty + " ret = (*env)->CallObjectMethod(env, obj, j_calls->" + fn_line.fn_name + "_meth"
elif fn_line.ret_ty_info.c_ty == "void":
- out_c += "\t(*env)->Call" + fn_line.ret_ty_info.java_ty.title() + "Method(env, obj, j_calls->" + fn_line.fn_name + "_meth"
- elif fn_line.ret_ty_info.java_ty == "String":
+ out_c += "\t(*env)->CallVoidMethod(env, obj, j_calls->" + fn_line.fn_name + "_meth"
+ elif fn_line.ret_ty_info.java_hu_ty == "String" or "org/ldk/enums" in fn_line.ret_ty_info.java_fn_ty_arg:
# Manually write out String methods as they're just an Object
out_c += "\t" + fn_line.ret_ty_info.c_ty + " ret = (*env)->CallObjectMethod(env, obj, j_calls->" + fn_line.fn_name + "_meth"
elif not fn_line.ret_ty_info.passed_as_ptr:
else:
out_c = out_c + ", " + var[1]
out_c = out_c + ");\n"
- out_c = out_c + "\treturn (uint64_t)res_ptr;\n"
+ out_c = out_c + "\treturn tag_ptr(res_ptr, true);\n"
out_c = out_c + "}\n"
for var in flattened_field_vars:
out_java += "\tpublic static native long " + struct_name + "_get_" + var[1] + "(long arg);\n"
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 + " *)(arg & ~1);\n"
- out_c += "\tuint64_t res_ptr = (uint64_t)&inp->" + var[1] + ";\n"
- out_c += "\tDO_ASSERT((res_ptr & 1) == 0);\n"
- out_c += "\treturn (int64_t)(res_ptr | 1);\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 += "}\n"
return (out_java, out_java_trait, out_c)
if idx > 0:
init_meth_params = init_meth_params + ", "
- if field_ty.java_hu_ty == var.var_name:
- field_path = field_ty.java_fn_ty_arg.strip("L;").replace("/", ".")
- out_java += "\t\t\tpublic " + field_path + " " + field_ty.arg_name + ";\n"
- java_hu_subclasses = java_hu_subclasses + "\t\tpublic final " + field_path + " " + field_ty.arg_name + ";\n"
- init_meth_params = init_meth_params + field_path + " " + field_ty.arg_name
- else:
- out_java += "\t\t\tpublic " + field_ty.java_ty + " " + field_ty.arg_name + ";\n"
- if field_docs is not None:
- java_hu_subclasses += "\t\t/**\n\t\t * " + field_docs.replace("\n", "\n\t\t * ") + "\n\t\t*/\n"
- java_hu_subclasses += "\t\t"
- if field_ty.nullable:
- java_hu_subclasses += "@Nullable "
- java_hu_subclasses += "public final " + field_ty.java_hu_ty + " " + field_ty.arg_name + ";\n"
- init_meth_params = init_meth_params + field_ty.java_ty + " " + field_ty.arg_name
+ java_ty = field_ty.java_ty
+ if field_ty.java_fn_ty_arg.startswith("L") and field_ty.java_fn_ty_arg.endswith(";"):
+ # If this is a simple enum, we have to reference it in the low-level bindings differently:
+ java_ty = field_ty.java_fn_ty_arg.strip("L;").replace("/", ".")
+ out_java += "\t\t\tpublic " + java_ty + " " + field_ty.arg_name + ";\n"
+ if field_docs is not None:
+ java_hu_subclasses += "\t\t/**\n\t\t * " + field_docs.replace("\n", "\n\t\t * ") + "\n\t\t*/\n"
+ java_hu_subclasses += "\t\t"
+ if field_ty.nullable:
+ java_hu_subclasses += "@Nullable "
+ java_hu_subclasses += "public final " + self.fully_qualified_hu_ty_path(field_ty) + " " + field_ty.arg_name + ";\n"
+ init_meth_params = init_meth_params + java_ty + " " + field_ty.arg_name
+
init_meth_body = init_meth_body + "this." + field_ty.arg_name + " = " + field_ty.arg_name + "; "
if field_ty.to_hu_conv is not None:
hu_conv_body = hu_conv_body + "\t\t\t" + field_ty.java_ty + " " + field_ty.arg_name + " = obj." + field_ty.arg_name + ";\n"
out_c += (self.c_complex_enum_pfx(struct_name, [x.var_name for x in variant_list], init_meth_jty_strs))
out_c += (self.c_fn_ty_pfx + self.c_complex_enum_pass_ty(struct_name) + " " + self.c_fn_name_define_pfx(struct_name + "_ref_from_ptr", True) + self.ptr_c_ty + " ptr) {\n")
- out_c += ("\t" + struct_name + " *obj = (" + struct_name + "*)(ptr & ~1);\n")
+ out_c += ("\t" + struct_name + " *obj = (" + struct_name + "*)untag_ptr(ptr);\n")
out_c += ("\tswitch(obj->tag) {\n")
for var in variant_list:
out_c += ("\t\tcase " + struct_name + "_" + var.var_name + ": {\n")
out_opaque_struct_human += "@SuppressWarnings(\"unchecked\") // We correctly assign various generic arrays\n"
hu_name = struct_name.replace("LDKC2Tuple", "TwoTuple").replace("LDKC3Tuple", "ThreeTuple").replace("LDK", "")
out_opaque_struct_human += ("public class " + hu_name + " extends CommonBase")
- if struct_name.startswith("LDKLocked"):
+ if struct_name.startswith("LDKLocked") or struct_name.startswith("LDKReadOnly"):
out_opaque_struct_human += (" implements AutoCloseable")
out_opaque_struct_human += (" {\n")
out_opaque_struct_human += ("\t" + hu_name + "(Object _dummy, long ptr) { super(ptr); }\n")
- if struct_name.startswith("LDKLocked"):
+ if struct_name.startswith("LDKLocked") or struct_name.startswith("LDKReadOnly"):
out_opaque_struct_human += ("\t@Override public void close() {\n")
else:
out_opaque_struct_human += ("\t@Override @SuppressWarnings(\"deprecation\")\n")