From 56e9910ffaa7fccf2cb777dc9cf55e01a9681543 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 26 Jan 2021 16:55:21 -0500 Subject: [PATCH] Do array conv in per-lang files, handle object arrays in TS --- gen_type_mapping.py | 26 ++++++++++---------------- genbindings.py | 13 +++++-------- java_strings.py | 27 ++++++++++++++++++++------- typescript_strings.py | 19 ++++++++++++++----- 4 files changed, 49 insertions(+), 36 deletions(-) diff --git a/gen_type_mapping.py b/gen_type_mapping.py index 5ad3d27f..9c05e5ec 100644 --- a/gen_type_mapping.py +++ b/gen_type_mapping.py @@ -2,11 +2,10 @@ from bindingstypes import ConvInfo class TypeMappingGenerator: - def __init__(self, java_c_types, consts, c_array_class_caches, opaque_structs, clone_fns, unitary_enums, trait_structs, complex_enums, result_types, tuple_types): + def __init__(self, java_c_types, consts, opaque_structs, clone_fns, unitary_enums, trait_structs, complex_enums, result_types, tuple_types): # trick our way around circular imports self.java_c_types = java_c_types self.consts = consts - self.c_array_class_caches = c_array_class_caches self.opaque_structs = opaque_structs self.clone_fns = clone_fns self.unitary_enums = unitary_enums @@ -120,26 +119,21 @@ class TypeMappingGenerator: ret_conv = (ty_info.rust_obj + " " + arr_name + "_var = ", "") if subty.ret_conv is None: ret_conv = ("DUMMY", "DUMMY") - elif not ty_info.java_ty[:len(ty_info.java_ty) - 2].endswith("[]"): + else: ret_conv = (ret_conv[0], ";\n" + ty_info.c_ty + " " + arr_name + "_arr = " + self.consts.create_native_arr_call(arr_name + "_var." + arr_len, ty_info) + ";\n") - ret_conv = (ret_conv[0], ret_conv[1] + subty.c_ty + " *" + arr_name + "_arr_ptr = " + self.consts.get_native_arr_ptr_call[0] + arr_name + "_arr" + self.consts.get_native_arr_ptr_call[1] + ";\n") + get_ptr_call = self.consts.get_native_arr_ptr_call(ty_info) + if get_ptr_call is not None: + ret_conv = (ret_conv[0], ret_conv[1] + subty.c_ty + " *" + arr_name + "_arr_ptr = " + get_ptr_call[0] + arr_name + "_arr" + get_ptr_call[1] + ";\n") ret_conv = (ret_conv[0], ret_conv[1] + "for (size_t " + idxc + " = 0; " + idxc + " < " + arr_name + "_var." + arr_len + "; " + idxc + "++) {\n") ret_conv = (ret_conv[0], ret_conv[1] + "\t" + subty.ret_conv[0].replace("\n", "\n\t")) ret_conv = (ret_conv[0], ret_conv[1] + arr_name + "_var." + ty_info.arr_access + "[" + idxc + "]" + subty.ret_conv[1].replace("\n", "\n\t")) - ret_conv = (ret_conv[0], ret_conv[1] + "\n\t" + arr_name + "_arr_ptr[" + idxc + "] = " + subty.ret_conv_name + ";\n}") - cleanup = self.consts.release_native_arr_ptr_call(arr_name + "_arr", arr_name + "_arr_ptr") + if get_ptr_call is not None: + ret_conv = (ret_conv[0], ret_conv[1] + "\n\t" + arr_name + "_arr_ptr[" + idxc + "] = " + subty.ret_conv_name + ";\n}") + else: + ret_conv = (ret_conv[0], ret_conv[1] + "\n\t" + self.consts.get_native_arr_entry_call(ty_info, arr_name + "_arr", idxc, subty.ret_conv_name) + ";\n}") + cleanup = self.consts.release_native_arr_ptr_call(ty_info, arr_name + "_arr", arr_name + "_arr_ptr") if cleanup is not None: ret_conv = (ret_conv[0], ret_conv[1] + "\n" + cleanup + ";") - else: - assert ty_info.java_fn_ty_arg.startswith("[") - clz_var = ty_info.java_fn_ty_arg[1:].replace("[", "arr_of_") - self.c_array_class_caches.add(clz_var) - ret_conv = (ret_conv[0], ";\n" + ty_info.c_ty + " " + arr_name + "_arr = (*env)->NewObjectArray(env, " + arr_name + "_var." + arr_len + ", " + clz_var + "_clz, NULL);\n") - ret_conv = (ret_conv[0], ret_conv[1] + "for (size_t " + idxc + " = 0; " + idxc + " < " + arr_name + "_var." + arr_len + "; " + idxc + "++) {\n") - ret_conv = (ret_conv[0], ret_conv[1] + "\t" + subty.ret_conv[0].replace("\n", "\n\t")) - ret_conv = (ret_conv[0], ret_conv[1] + arr_name + "_var." + ty_info.arr_access + "[" + idxc + "]" + subty.ret_conv[1].replace("\n", "\n\t")) - ret_conv = (ret_conv[0], ret_conv[1] + "\n\t(*env)->SetObjectArrayElement(env, " + arr_name + "_arr, " + idxc + ", " + subty.ret_conv_name + ");\n") - ret_conv = (ret_conv[0], ret_conv[1] + "}") if not holds_ref: # XXX: The commented if's are a bit smarter freeing, but we need to be a nudge smarter still # Note that we don't drop the full vec here - we're passing ownership to java (or have cloned) or free'd by now! diff --git a/genbindings.py b/genbindings.py index 32cad50a..3a655143 100755 --- a/genbindings.py +++ b/genbindings.py @@ -332,13 +332,9 @@ fn_ret_arr_regex = re.compile("(.*) \(\*(.*)\((.*)\)\)\[([0-9]*)\];$") reg_fn_regex = re.compile("([A-Za-z_0-9\* ]* \*?)([a-zA-Z_0-9]*)\((.*)\);$") clone_fns = set() constructor_fns = {} -c_array_class_caches = set() - from gen_type_mapping import TypeMappingGenerator -type_mapping_generator = TypeMappingGenerator(java_c_types, consts, c_array_class_caches, opaque_structs, clone_fns, unitary_enums, trait_structs, complex_enums, result_types, tuple_types) - - +type_mapping_generator = TypeMappingGenerator(java_c_types, consts, opaque_structs, clone_fns, unitary_enums, trait_structs, complex_enums, result_types, tuple_types) with open(sys.argv[1]) as in_h: for line in in_h: @@ -947,7 +943,8 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: write_c("\t\tret->data = NULL;\n") write_c("\t} else {\n") write_c("\t\tret->data = MALLOC(sizeof(" + vec_ty + ") * ret->datalen, \"" + struct_name + " Data\");\n") - write_c("\t\t" + ty_info.c_ty + " *java_elems = " + consts.get_native_arr_ptr_call[0] + "elems" + consts.get_native_arr_ptr_call[1] + ";\n") + native_arr_ptr_call = consts.get_native_arr_ptr_call(ty_info.ty_info) + write_c("\t\t" + ty_info.c_ty + " *java_elems = " + native_arr_ptr_call[0] + "elems" + native_arr_ptr_call[1] + ";\n") write_c("\t\tfor (size_t i = 0; i < ret->datalen; i++) {\n") if ty_info.arg_conv is not None: write_c("\t\t\t" + ty_info.c_ty + " arr_elem = java_elems[i];\n") @@ -957,7 +954,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: else: write_c("\t\t\tret->data[i] = java_elems[i];\n") write_c("\t\t}\n") - cleanup = consts.release_native_arr_ptr_call("elems", "java_elems") + cleanup = consts.release_native_arr_ptr_call(ty_info.ty_info, "elems", "java_elems") if cleanup is not None: write_c("\t\t" + cleanup + ";\n") write_c("\t}\n") @@ -1047,5 +1044,5 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: out_java_struct.write("}\n") with open(sys.argv[4], "w") as out_c: out_c.write(consts.c_file_pfx) - out_c.write(consts.init_str(c_array_class_caches)) + out_c.write(consts.init_str()) out_c.write(c_file) diff --git a/java_strings.py b/java_strings.py index 04855ce9..587d8281 100644 --- a/java_strings.py +++ b/java_strings.py @@ -2,7 +2,7 @@ from bindingstypes import * class Consts: def __init__(self, DEBUG: bool, **kwargs): - + self.c_array_class_caches = set() self.c_type_map = dict( uint8_t = ['byte'], uint16_t = ['short'], @@ -300,13 +300,18 @@ import java.util.Arrays; self.owned_str_to_c_call = ("(*env)->NewStringUTF(env, ", ")") self.ptr_arr = "jobjectArray" self.get_native_arr_len_call = ("(*env)->GetArrayLength(env, ", ")") - self.get_native_arr_ptr_call = ("(*env)->GetPrimitiveArrayCritical(env, ", ", NULL)") - def release_native_arr_ptr_call(self, arr_var, arr_ptr_var): - return "(*env)->ReleasePrimitiveArrayCritical(env, " + arr_var + ", " + arr_ptr_var + ", 0)" + def release_native_arr_ptr_call(self, ty_info, arr_var, arr_ptr_var): + if ty_info.subty is None or not ty_info.subty.c_ty.endswith("Array"): + return "(*env)->ReleasePrimitiveArrayCritical(env, " + arr_var + ", " + arr_ptr_var + ", 0)" + return None def create_native_arr_call(self, arr_len, ty_info): if ty_info.c_ty == "int8_tArray": return "(*env)->NewByteArray(env, " + arr_len + ")" + elif ty_info.subty.c_ty.endswith("Array"): + 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" 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): @@ -329,18 +334,26 @@ import java.util.Arrays; return "(*env)->GetObjectArrayElement(env, " + arr_name + ", " + idxc + ")" else: assert False # Only called if above is None + def get_native_arr_ptr_call(self, ty_info): + if ty_info.subty is not None and ty_info.subty.c_ty.endswith("Array"): + return None + return ("(*env)->GetPrimitiveArrayCritical(env, ", ", NULL)") + def get_native_arr_entry_call(self, ty_info, arr_name, idxc, entry_access): + if ty_info.subty is None or not ty_info.subty.c_ty.endswith("Array"): + return None + return "(*env)->SetObjectArrayElement(env, " + arr_name + ", " + idxc + ", " + entry_access + ")" def cleanup_native_arr_ref_contents(self, arr_name, dest_name, arr_len, ty_info): if ty_info.c_ty == "int8_tArray": return "(*env)->ReleaseByteArrayElements(env, " + arr_name + ", (int8_t*)" + dest_name + ", 0);" else: return "(*env)->Release" + ty_info.java_ty.strip("[]").title() + "ArrayElements(env, " + arr_name + ", " + dest_name + ", 0)" - def init_str(self, c_array_class_caches): + def init_str(self): res = "" - for ty in c_array_class_caches: + for ty in self.c_array_class_caches: res = res + "static jclass " + ty + "_clz = NULL;\n" res = res + "JNIEXPORT void Java_org_ldk_impl_bindings_init_1class_1cache(JNIEnv * env, jclass clz) {\n" - for ty in c_array_class_caches: + for ty in 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" diff --git a/typescript_strings.py b/typescript_strings.py index e631237c..0e13c8d6 100644 --- a/typescript_strings.py +++ b/typescript_strings.py @@ -85,7 +85,7 @@ void *memcpy(void *dest, const void *src, size_t n); int memcmp(const void *s1, const void *s2, size_t n); void __attribute__((noreturn)) abort(void); -void assert(scalar expression); +void assert(bool expression); """ if not DEBUG: @@ -198,6 +198,7 @@ _Static_assert(sizeof(void*) == 4, "Pointers mut be 32 bits"); typedef struct int64_tArray {uint32_t len;int64_t *ptr;} int64_tArray; typedef struct uint32_tArray {uint32_t len;int32_t *ptr;} uint32_tArray; +typedef struct ptrArray {uint32_t len;int32_t *ptr;} ptrArray; typedef struct int8_tArray {uint32_t len;int8_t *ptr;} int8_tArray; typedef struct jstring {} jstring; @@ -220,11 +221,10 @@ import * as bindings from '../bindings' // TODO: figure out location self.ptr_native_ty = "number" # "uint32_t" self.result_c_ty = "uint32_t" self.owned_str_to_c_call = ("conv_owned_string(", ")") - self.ptr_arr = "uint32_tArray" + self.ptr_arr = "ptrArray" self.get_native_arr_len_call = ("", ".len") - self.get_native_arr_ptr_call = ("", ".ptr") - def release_native_arr_ptr_call(self, arr_var, arr_ptr_var): + def release_native_arr_ptr_call(self, ty_info, arr_var, arr_ptr_var): return None def create_native_arr_call(self, arr_len, ty_info): if ty_info.c_ty == "int8_tArray": @@ -233,6 +233,9 @@ import * as bindings from '../bindings' // TODO: figure out location return "{ .len = " + arr_len + ", .ptr = MALLOC(" + arr_len + " * sizeof(int64_t), \"Native " + ty_info.c_ty + " Bytes\") }" elif ty_info.c_ty == "uint32_tArray": return "{ .len = " + arr_len + ", .ptr = MALLOC(" + arr_len + " * sizeof(int32_t), \"Native " + ty_info.c_ty + " Bytes\") }" + elif ty_info.c_ty == "ptrArray": + assert ty_info.subty is not None and ty_info.subty.c_ty.endswith("Array") + return "{ .len = " + arr_len + ", .ptr = MALLOC(" + arr_len + " * sizeof(int32_t), \"Native Object Bytes\") }" else: print("Need to create arr!", ty_info.c_ty) return ty_info.c_ty @@ -251,6 +254,12 @@ import * as bindings from '../bindings' // TODO: figure out location return "(" + ty_info.subty.c_ty + "*) " + arr_name + ".ptr" def get_native_arr_elem(self, arr_name, idxc, ty_info): assert False # Only called if above is None + def get_native_arr_ptr_call(self, ty_info): + if ty_info.subty is not None: + return ("(" + ty_info.subty.c_ty + "*)", ".ptr") + return ("(" + ty_info.c_ty + "*)", ".ptr") + def get_native_arr_entry_call(self, ty_info, arr_name, idxc, entry_access): + return None def cleanup_native_arr_ref_contents(self, arr_name, dest_name, arr_len, ty_info): if ty_info.c_ty == "int8_tArray": return None @@ -275,7 +284,7 @@ const wasm = wasmInstance.exports; """ return '' - def init_str(self, c_array_class_caches): + def init_str(self): return "" def native_c_unitary_enum_map(self, struct_name, variants): -- 2.39.5