X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=java_strings.py;h=f97ca9b7d0cff3ac4b416f175c8add0d10c9d040;hb=17731f152e9d722247c54fd81111ce49ab5b7a27;hp=94998db17a6dbade2c919bc505ca3a7b9821236f;hpb=8108649e5097ff0c512748552e9ffe0398663b9d;p=ldk-java diff --git a/java_strings.py b/java_strings.py index 94998db1..f97ca9b7 100644 --- a/java_strings.py +++ b/java_strings.py @@ -1,5 +1,6 @@ from bindingstypes import * from enum import Enum +import sys class Target(Enum): JAVA = 1, @@ -23,6 +24,12 @@ class Consts: self.bindings_header = """package org.ldk.impl; import org.ldk.enums.*; +import java.io.File; +import java.io.InputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; public class bindings { public static class VecOrSliceDef { @@ -34,7 +41,24 @@ public class bindings { } } static { - System.loadLibrary(\"lightningjni\"); + try { + // Try to load natively first, this works on Android and in testing. + System.loadLibrary(\"lightningjni\"); + } catch (UnsatisfiedLinkError _ignored) { + // Otherwise try to load from the library jar. + File tmpdir = new File(System.getProperty("java.io.tmpdir"), "ldk-java-nativelib"); + tmpdir.mkdir(); // If it fails to create, assume it was there already + tmpdir.deleteOnExit(); + String libname = "liblightningjni_" + System.getProperty("os.name").replaceAll(" ", "") + + "-" + System.getProperty("os.arch").replaceAll(" ", "") + ".nativelib"; + try (InputStream is = bindings.class.getResourceAsStream("/" + libname)) { + Path libpath = new File(tmpdir.toPath().toString(), "liblightningjni.so").toPath(); + Files.copy(is, libpath, StandardCopyOption.REPLACE_EXISTING); + Runtime.getRuntime().load(libpath.toString()); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } init(java.lang.Enum.class, VecOrSliceDef.class); init_class_cache(); if (!get_lib_version_string().equals(get_ldk_java_bindings_version())) @@ -83,11 +107,13 @@ class CommonBase { long ptr; LinkedList ptrs_to = new LinkedList(); protected CommonBase(long ptr) { this.ptr = ptr; } - public long _test_only_get_ptr() { return this.ptr; } } """ - self.c_file_pfx = """#include \"org_ldk_impl_bindings.h\" + self.c_file_pfx = """#include +// On OSX jlong (ie long long) is not equivalent to int64_t, so we override here +#define int64_t jlong +#include \"org_ldk_impl_bindings.h\" #include #include #include @@ -124,13 +150,15 @@ 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: + if not DEBUG or sys.platform == "darwin": self.c_file_pfx = self.c_file_pfx + """#define MALLOC(a, _) malloc(a) #define FREE(p) if ((uint64_t)(p) > 1024) { free(p); } -#define DO_ASSERT(a) (void)(a) +""" + if not DEBUG: + self.c_file_pfx += """#define DO_ASSERT(a) (void)(a) #define CHECK(a) """ - else: + if DEBUG: self.c_file_pfx = self.c_file_pfx + """#include // Always run a, then assert it is true: #define DO_ASSERT(a) do { bool _assert_val = (a); assert(_assert_val); } while(0) @@ -144,7 +172,10 @@ void __attribute__((constructor)) debug_log_version() { DEBUG_PRINT("LDK C Bindings version did not match the header we built against\\n"); DEBUG_PRINT("Loaded LDK-Java Bindings with LDK %s and LDK-C-Bindings %s\\n", check_get_ldk_version(), check_get_ldk_bindings_version()); } +""" + if sys.platform != "darwin": + 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 // linker option to wrap malloc/calloc/realloc/free, tracking everyhing allocated @@ -152,8 +183,8 @@ void __attribute__((constructor)) debug_log_version() { #include """ - if self.target == Target.ANDROID: - self.c_file_pfx = self.c_file_pfx + """ + if self.target == Target.ANDROID: + self.c_file_pfx = self.c_file_pfx + """ #include #include @@ -194,9 +225,9 @@ void backtrace_symbols_fd(void ** buffer, int count, int _fd) { } } """ - else: - self.c_file_pfx = self.c_file_pfx + "#include \n" - self.c_file_pfx = self.c_file_pfx + """ + else: + self.c_file_pfx = self.c_file_pfx + "#include \n" + self.c_file_pfx = self.c_file_pfx + """ #include static mtx_t allocation_mtx; @@ -457,7 +488,10 @@ import java.util.Arrays; res = "JNIEnv *env;\n" res += "jint get_jenv_res = (*j_calls->vm)->GetEnv(j_calls->vm, (void**)&env, JNI_VERSION_1_6);\n" res += "if (get_jenv_res == JNI_EDETACHED) {\n" - res += "\tDO_ASSERT((*j_calls->vm)->AttachCurrentThread(j_calls->vm, (void**)&env, NULL) == JNI_OK);\n" + if self.target == Target.ANDROID: + res += "\tDO_ASSERT((*j_calls->vm)->AttachCurrentThread(j_calls->vm, &env, NULL) == JNI_OK);\n" + else: + res += "\tDO_ASSERT((*j_calls->vm)->AttachCurrentThread(j_calls->vm, (void**)&env, NULL) == JNI_OK);\n" res += "} else {\n" res += "\tDO_ASSERT(get_jenv_res == JNI_OK);\n" res += "}\n" @@ -541,7 +575,7 @@ import java.util.Arrays; out_java_enum = "package org.ldk.enums;\n\n" out_java = "" out_c = "" - out_c = out_c + "static inline " + struct_name + " " + struct_name + "_from_java(" + self.c_fn_args_pfx + ") {\n" + out_c = out_c + "static inline LDK" + struct_name + " LDK" + struct_name + "_from_java(" + self.c_fn_args_pfx + ") {\n" out_c = out_c + "\tswitch ((*env)->CallIntMethod(env, clz, ordinal_meth)) {\n" if enum_doc_comment is not None: @@ -570,7 +604,7 @@ import java.util.Arrays; out_c = out_c + "\t" + struct_name + "_" + var + " = (*env)->GetStaticFieldID(env, " + struct_name + "_class, \"" + var + "\", \"Lorg/ldk/enums/" + struct_name + ";\");\n" out_c = out_c + "\tCHECK(" + struct_name + "_" + var + " != NULL);\n" out_c = out_c + "}\n" - out_c = out_c + "static inline jclass " + struct_name + "_to_java(JNIEnv *env, " + struct_name + " val) {\n" + out_c = out_c + "static inline jclass LDK" + struct_name + "_to_java(JNIEnv *env, LDK" + struct_name + " val) {\n" out_c = out_c + "\tswitch (val) {\n" ord_v = 0 for var in variants: @@ -820,6 +854,12 @@ import java.util.Arrays; else: out_c = out_c + ", " + arg_info.arg_name out_c = out_c + ");\n" + + out_c += "\tif ((*env)->ExceptionCheck(env)) {\n" + out_c += "\t\t(*env)->ExceptionDescribe(env);\n" + out_c += "\t\t(*env)->FatalError(env, \"A call to " + fn_line.fn_name + " in " + struct_name + " from rust threw an exception.\");\n" + out_c += "\t}\n" + if fn_line.ret_ty_info.arg_conv is not None: out_c += "\t" + fn_line.ret_ty_info.arg_conv.replace("\n", "\n\t") + "\n" out_c += "\t" + self.deconstruct_jenv().replace("\n", "\n\t").strip() + "\n" @@ -956,8 +996,19 @@ import java.util.Arrays; init_meth_body = "" hu_conv_body = "" for idx, field_ty in enumerate(var.fields): - out_java += ("\t\t\tpublic " + field_ty.java_ty + " " + field_ty.arg_name + ";\n") - java_hu_subclasses = java_hu_subclasses + "\t\tpublic final " + field_ty.java_hu_ty + " " + field_ty.arg_name + ";\n" + 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" + java_hu_subclasses = java_hu_subclasses + "\t\tpublic 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 + 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" hu_conv_body = hu_conv_body + "\t\t\t" + field_ty.to_hu_conv.replace("\n", "\n\t\t\t") + "\n" @@ -965,10 +1016,6 @@ import java.util.Arrays; else: hu_conv_body = hu_conv_body + "\t\t\tthis." + field_ty.arg_name + " = obj." + field_ty.arg_name + ";\n" init_meth_jty_str = init_meth_jty_str + field_ty.java_fn_ty_arg - if idx > 0: - init_meth_params = init_meth_params + ", " - init_meth_params = init_meth_params + field_ty.java_ty + " " + field_ty.arg_name - init_meth_body = init_meth_body + "this." + field_ty.arg_name + " = " + field_ty.arg_name + "; " out_java += ("\t\t\t" + var.var_name + "(" + init_meth_params + ") { ") out_java += (init_meth_body) out_java += ("}\n") @@ -1034,7 +1081,7 @@ import java.util.Arrays; return out_opaque_struct_human - def map_function(self, argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, args_known, type_mapping_generator, doc_comment): + def map_function(self, argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, takes_self_as_ref, args_known, type_mapping_generator, doc_comment): out_java = "" out_c = "" out_java_struct = None @@ -1061,7 +1108,7 @@ import java.util.Arrays; if not args_known: out_java_struct += ("\t// Skipped " + method_name + "\n") else: - meth_n = method_name[len(struct_meth) + 1:].strip("_") + meth_n = method_name[len(struct_meth) + 1 if len(struct_meth) != 0 else 0:].strip("_") if doc_comment is not None: out_java_struct += "\t/**\n\t * " + doc_comment.replace("\n", "\n\t * ") + "\n\t */\n" if not takes_self: @@ -1076,7 +1123,7 @@ import java.util.Arrays; for idx, arg in enumerate(argument_types): if idx != 0: if not takes_self or idx > 1: - out_java_struct += (", ") + out_java_struct += ", " elif takes_self: continue if arg.java_ty != "void": @@ -1177,6 +1224,8 @@ import java.util.Arrays; else: out_java_struct += ("\t\t" + info.from_hu_conv[1].replace("\n", "\n\t\t") + ";\n") + if takes_self and not takes_self_as_ref: + out_java_struct += "\t\t" + argument_types[0].from_hu_conv[1].replace("\n", "\n\t\t").replace("this_arg", "this") + ";\n" if return_type_info.to_hu_conv_name is not None: out_java_struct += ("\t\treturn " + return_type_info.to_hu_conv_name + ";\n") elif return_type_info.java_ty != "void" and return_type_info.rust_obj != "LDK" + struct_meth: