- is_log = fn_line.group(2) == "log" and struct_name == "LDKLogger"
- if fn_line.group(2) != "free" and fn_line.group(2) != "clone" and fn_line.group(2) != "eq" and not is_log:
- dummy_line = fn_line.group(1) + struct_name.replace("LDK", "") + "_call_" + fn_line.group(2) + " " + struct_name + "* this_arg" + fn_line.group(4) + "\n"
- map_fn(dummy_line, re.compile("([A-Za-z_0-9]*) *([A-Za-z_0-9]*) *(.*)").match(dummy_line), None, "(this_arg_conv->" + fn_line.group(2) + ")(this_arg_conv->this_arg")
-
- out_c.write("""#include \"org_ldk_impl_bindings.h\"
-#include <rust_types.h>
-#include <lightning.h>
-#include <string.h>
-#include <stdatomic.h>
-""")
-
- if sys.argv[4] == "false":
- out_c.write("#define MALLOC(a, _) malloc(a)\n")
- out_c.write("#define FREE free\n")
- out_c.write("#define DO_ASSERT(a) (void)(a)\n")
- else:
- out_c.write("""#include <assert.h>
-#define DO_ASSERT(a) do { bool _assert_val = (a); assert(_assert_val); } while(0)
-
-// 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
-// and free'd in Rust or C across the generated bindings shared library.
-#include <threads.h>
-#include <execinfo.h>
-#include <unistd.h>
-static mtx_t allocation_mtx;
-
-void __attribute__((constructor)) init_mtx() {
- DO_ASSERT(mtx_init(&allocation_mtx, mtx_plain) == thrd_success);
-}
-
-#define BT_MAX 128
-typedef struct allocation {
- struct allocation* next;
- void* ptr;
- const char* struct_name;
- void* bt[BT_MAX];
- int bt_len;
-} allocation;
-static allocation* allocation_ll = NULL;
-
-void* __real_malloc(size_t len);
-void* __real_calloc(size_t nmemb, size_t len);
-static void new_allocation(void* res, const char* struct_name) {
- allocation* new_alloc = __real_malloc(sizeof(allocation));
- new_alloc->ptr = res;
- new_alloc->struct_name = struct_name;
- new_alloc->bt_len = backtrace(new_alloc->bt, BT_MAX);
- DO_ASSERT(mtx_lock(&allocation_mtx) == thrd_success);
- new_alloc->next = allocation_ll;
- allocation_ll = new_alloc;
- DO_ASSERT(mtx_unlock(&allocation_mtx) == thrd_success);
-}
-static void* MALLOC(size_t len, const char* struct_name) {
- void* res = __real_malloc(len);
- new_allocation(res, struct_name);
- return res;
-}
-void __real_free(void* ptr);
-static void alloc_freed(void* ptr) {
- allocation* p = NULL;
- DO_ASSERT(mtx_lock(&allocation_mtx) == thrd_success);
- allocation* it = allocation_ll;
- while (it->ptr != ptr) { p = it; it = it->next; }
- if (p) { p->next = it->next; } else { allocation_ll = it->next; }
- DO_ASSERT(mtx_unlock(&allocation_mtx) == thrd_success);
- DO_ASSERT(it->ptr == ptr);
- __real_free(it);
-}
-static void FREE(void* ptr) {
- alloc_freed(ptr);
- __real_free(ptr);
-}
-
-void* __wrap_malloc(size_t len) {
- void* res = __real_malloc(len);
- new_allocation(res, "malloc call");
- return res;
-}
-void* __wrap_calloc(size_t nmemb, size_t len) {
- void* res = __real_calloc(nmemb, len);
- new_allocation(res, "calloc call");
- return res;
-}
-void __wrap_free(void* ptr) {
- 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);
- void* res = __real_realloc(ptr, len);
- new_allocation(res, "realloc call");
- return res;
-}
-void __wrap_reallocarray(void* ptr, size_t new_sz) {
- // Rust doesn't seem to use reallocarray currently
- assert(false);
-}
-
-void __attribute__((destructor)) check_leaks() {
- for (allocation* a = allocation_ll; a != NULL; a = a->next) {
- fprintf(stderr, "%s %p remains:\\n", a->struct_name, a->ptr);
- backtrace_symbols_fd(a->bt, a->bt_len, STDERR_FILENO);
- fprintf(stderr, "\\n\\n");
- }
- DO_ASSERT(allocation_ll == NULL);
-}
-""")
- out_java.write("""package org.ldk.impl;
-import org.ldk.enums.*;
-
-public class bindings {
- public static class VecOrSliceDef {
- public long dataptr;
- public long datalen;
- public long stride;
- public VecOrSliceDef(long dataptr, long datalen, long stride) {
- this.dataptr = dataptr; this.datalen = datalen; this.stride = stride;
- }
- }
- static {
- System.loadLibrary(\"lightningjni\");
- init(java.lang.Enum.class, VecOrSliceDef.class);
- }
- static native void init(java.lang.Class c, java.lang.Class slicedef);
-
- public static native boolean deref_bool(long ptr);
- public static native long deref_long(long ptr);
- public static native void free_heap_ptr(long ptr);
- public static native byte[] read_bytes(long ptr, long len);
- public static native byte[] get_u8_slice_bytes(long slice_ptr);
- public static native long bytes_to_u8_vec(byte[] bytes);
- public static native long new_txpointer_copy_data(byte[] txdata);
- public static native long vec_slice_len(long vec);
- public static native long new_empty_slice_vec();
-
-""")
- out_c.write("""
-static jmethodID ordinal_meth = NULL;
-static jmethodID slicedef_meth = NULL;
-static jclass slicedef_cls = NULL;
-JNIEXPORT void Java_org_ldk_impl_bindings_init(JNIEnv * env, jclass _b, jclass enum_class, jclass slicedef_class) {
- ordinal_meth = (*env)->GetMethodID(env, enum_class, "ordinal", "()I");
- DO_ASSERT(ordinal_meth != NULL);
- slicedef_meth = (*env)->GetMethodID(env, slicedef_class, "<init>", "(JJJ)V");
- DO_ASSERT(slicedef_meth != NULL);
- slicedef_cls = (*env)->NewGlobalRef(env, slicedef_class);
- DO_ASSERT(slicedef_cls != NULL);
-}
-
-JNIEXPORT jboolean JNICALL Java_org_ldk_impl_bindings_deref_1bool (JNIEnv * env, jclass _a, jlong ptr) {
- return *((bool*)ptr);
-}
-JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_deref_1long (JNIEnv * env, jclass _a, jlong ptr) {
- return *((long*)ptr);
-}
-JNIEXPORT void JNICALL Java_org_ldk_impl_bindings_free_1heap_1ptr (JNIEnv * env, jclass _a, jlong ptr) {
- FREE((void*)ptr);
-}
-JNIEXPORT jbyteArray JNICALL Java_org_ldk_impl_bindings_read_1bytes (JNIEnv * _env, jclass _b, jlong ptr, jlong len) {
- jbyteArray ret_arr = (*_env)->NewByteArray(_env, len);
- (*_env)->SetByteArrayRegion(_env, ret_arr, 0, len, (unsigned char*)ptr);
- return ret_arr;
-}
-JNIEXPORT jbyteArray JNICALL Java_org_ldk_impl_bindings_get_1u8_1slice_1bytes (JNIEnv * _env, jclass _b, jlong slice_ptr) {
- LDKu8slice *slice = (LDKu8slice*)slice_ptr;
- jbyteArray ret_arr = (*_env)->NewByteArray(_env, slice->datalen);
- (*_env)->SetByteArrayRegion(_env, ret_arr, 0, slice->datalen, slice->data);
- return ret_arr;
-}
-JNIEXPORT long JNICALL Java_org_ldk_impl_bindings_bytes_1to_1u8_1vec (JNIEnv * _env, jclass _b, jbyteArray bytes) {
- LDKCVec_u8Z *vec = (LDKCVec_u8Z*)MALLOC(sizeof(LDKCVec_u8Z), "LDKCVec_u8");
- vec->datalen = (*_env)->GetArrayLength(_env, bytes);
- vec->data = (uint8_t*)MALLOC(vec->datalen, "LDKCVec_u8Z Bytes");
- (*_env)->GetByteArrayRegion (_env, bytes, 0, vec->datalen, vec->data);
- return (long)vec;
-}
-JNIEXPORT long JNICALL Java_org_ldk_impl_bindings_new_1txpointer_1copy_1data (JNIEnv * env, jclass _b, jbyteArray bytes) {
- LDKTransaction *txdata = (LDKTransaction*)MALLOC(sizeof(LDKTransaction), "LDKTransaction");
- txdata->datalen = (*env)->GetArrayLength(env, bytes);
- txdata->data = (uint8_t*)MALLOC(txdata->datalen, "Tx Data Bytes");
- txdata->data_is_owned = true;
- (*env)->GetByteArrayRegion (env, bytes, 0, txdata->datalen, txdata->data);
- return (long)txdata;
-}
-JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_vec_1slice_1len (JNIEnv * env, jclass _a, jlong ptr) {
- // Check offsets of a few Vec types are all consistent as we're meant to be generic across types
- _Static_assert(offsetof(LDKCVec_u8Z, datalen) == offsetof(LDKCVec_SignatureZ, datalen), "Vec<*> needs to be mapped identically");
- _Static_assert(offsetof(LDKCVec_u8Z, datalen) == offsetof(LDKCVec_MessageSendEventZ, datalen), "Vec<*> needs to be mapped identically");
- _Static_assert(offsetof(LDKCVec_u8Z, datalen) == offsetof(LDKCVec_EventZ, datalen), "Vec<*> needs to be mapped identically");
- _Static_assert(offsetof(LDKCVec_u8Z, datalen) == offsetof(LDKCVec_C2Tuple_usizeTransactionZZ, datalen), "Vec<*> needs to be mapped identically");
- LDKCVec_u8Z *vec = (LDKCVec_u8Z*)ptr;
- return (long)vec->datalen;
-}
-JNIEXPORT long JNICALL Java_org_ldk_impl_bindings_new_1empty_1slice_1vec (JNIEnv * _env, jclass _b) {
- // Check sizes of a few Vec types are all consistent as we're meant to be generic across types
- _Static_assert(sizeof(LDKCVec_u8Z) == sizeof(LDKCVec_SignatureZ), "Vec<*> needs to be mapped identically");
- _Static_assert(sizeof(LDKCVec_u8Z) == sizeof(LDKCVec_MessageSendEventZ), "Vec<*> needs to be mapped identically");
- _Static_assert(sizeof(LDKCVec_u8Z) == sizeof(LDKCVec_EventZ), "Vec<*> needs to be mapped identically");
- _Static_assert(sizeof(LDKCVec_u8Z) == sizeof(LDKCVec_C2Tuple_usizeTransactionZZ), "Vec<*> needs to be mapped identically");
- LDKCVec_u8Z *vec = (LDKCVec_u8Z*)MALLOC(sizeof(LDKCVec_u8Z), "Empty LDKCVec");
- vec->data = NULL;
- vec->datalen = 0;
- return (long)vec;
-}
-
-// We assume that CVec_u8Z and u8slice are the same size and layout (and thus pointers to the two can be mixed)
-_Static_assert(sizeof(LDKCVec_u8Z) == sizeof(LDKu8slice), "Vec<u8> and [u8] need to have been mapped identically");
-_Static_assert(offsetof(LDKCVec_u8Z, data) == offsetof(LDKu8slice, data), "Vec<u8> and [u8] need to have been mapped identically");
-_Static_assert(offsetof(LDKCVec_u8Z, datalen) == offsetof(LDKu8slice, datalen), "Vec<u8> and [u8] need to have been mapped identically");
-
-""")
-
- with open(sys.argv[3] + "/structs/CommonBase.java", "a") as out_java_struct:
- out_java_struct.write("""package org.ldk.structs;
-import java.util.LinkedList;
-class CommonBase {
- final long ptr;
- LinkedList<Object> ptrs_to = new LinkedList();
- protected CommonBase(long ptr) { this.ptr = ptr; }
- public long _test_only_get_ptr() { return this.ptr; }
-}
-""")
+ is_log = fn_line.group(3) == "log" and struct_name == "LDKLogger"
+ if fn_line.group(3) != "free" and fn_line.group(3) != "clone" and fn_line.group(3) != "eq" and not is_log:
+ dummy_line = fn_line.group(2) + struct_name.replace("LDK", "") + "_" + fn_line.group(3) + " " + struct_name + "* this_arg" + fn_line.group(5) + "\n"
+ map_fn(dummy_line, re.compile("([A-Za-z_0-9]*) *([A-Za-z_0-9]*) *(.*)").match(dummy_line), None, "(this_arg_conv->" + fn_line.group(3) + ")(this_arg_conv->this_arg")
+ for idx, var_line in enumerate(field_var_lines):
+ if var_line.group(1) not in trait_structs:
+ write_c(var_line.group(1) + " " + struct_name + "_set_get_" + var_line.group(2) + "(" + struct_name + "* this_arg) {\n")
+ write_c("\tif (this_arg->set_" + var_line.group(2) + " != NULL)\n")
+ write_c("\t\tthis_arg->set_" + var_line.group(2) + "(this_arg);\n")
+ write_c("\treturn this_arg->" + var_line.group(2) + ";\n")
+ write_c("}\n")
+ dummy_line = var_line.group(1) + " " + struct_name.replace("LDK", "") + "_get_" + var_line.group(2) + " " + struct_name + "* this_arg" + fn_line.group(5) + "\n"
+ map_fn(dummy_line, re.compile("([A-Za-z_0-9]*) *([A-Za-z_0-9]*) *(.*)").match(dummy_line), None, struct_name + "_set_get_" + var_line.group(2) + "(this_arg_conv")
+
+ def map_result(struct_name, res_ty, err_ty):
+ result_types.add(struct_name)
+ human_ty = struct_name.replace("LDKCResult", "Result")
+ with open(f"{sys.argv[3]}/structs/{human_ty}{consts.file_ext}", "w") as out_java_struct:
+ out_java_struct.write(consts.hu_struct_file_prefix)
+ out_java_struct.write("public class " + human_ty + " extends CommonBase {\n")
+ out_java_struct.write("\tprivate " + human_ty + "(Object _dummy, long ptr) { super(ptr); }\n")
+ out_java_struct.write("\tprotected void finalize() throws Throwable {\n")
+ out_java_struct.write("\t\tif (ptr != 0) { bindings." + struct_name.replace("LDK","") + "_free(ptr); } super.finalize();\n")
+ out_java_struct.write("\t}\n\n")
+ out_java_struct.write("\tstatic " + human_ty + " constr_from_ptr(long ptr) {\n")
+ out_java_struct.write("\t\tif (bindings." + struct_name + "_result_ok(ptr)) {\n")
+ out_java_struct.write("\t\t\treturn new " + human_ty + "_OK(null, ptr);\n")
+ out_java_struct.write("\t\t} else {\n")
+ out_java_struct.write("\t\t\treturn new " + human_ty + "_Err(null, ptr);\n")
+ out_java_struct.write("\t\t}\n")
+ out_java_struct.write("\t}\n")
+
+ res_map = type_mapping_generator.map_type(res_ty + " res", True, None, False, True)
+ err_map = type_mapping_generator.map_type(err_ty + " err", True, None, False, True)
+ can_clone = True
+ if not res_map.is_native_primitive and (res_map.rust_obj.replace("LDK", "") + "_clone" not in clone_fns):
+ can_clone = False
+ if not err_map.is_native_primitive and (err_map.rust_obj.replace("LDK", "") + "_clone" not in clone_fns):
+ can_clone = False
+
+ out_java.write("\tpublic static native boolean " + struct_name + "_result_ok(long arg);\n")
+ write_c(consts.c_fn_ty_pfx + "jboolean " + consts.c_fn_name_pfx + struct_name.replace("_", "_1") + "_1result_1ok (" + consts.c_fn_args_pfx + ", " + consts.ptr_c_ty + " arg) {\n")
+ write_c("\treturn ((" + struct_name + "*)arg)->result_ok;\n")
+ write_c("}\n")
+
+ out_java.write("\tpublic static native " + res_map.java_ty + " " + struct_name + "_get_ok(long arg);\n")
+ write_c(consts.c_fn_ty_pfx + res_map.c_ty + " " + consts.c_fn_name_pfx + struct_name.replace("_", "_1") + "_1get_1ok (" + consts.c_fn_args_pfx + ", " + consts.ptr_c_ty + " arg) {\n")
+ write_c("\t" + struct_name + " *val = (" + struct_name + "*)arg;\n")
+ write_c("\tCHECK(val->result_ok);\n\t")
+ out_java_struct.write("\tpublic static final class " + human_ty + "_OK extends " + human_ty + " {\n")
+ if res_map.ret_conv is not None:
+ write_c(res_map.ret_conv[0].replace("\n", "\n\t") + "(*val->contents.result)")
+ write_c(res_map.ret_conv[1].replace("\n", "\n\t") + "\n\treturn " + res_map.ret_conv_name)
+ else:
+ write_c("return *val->contents.result")
+ write_c(";\n}\n")
+
+ if res_map.java_hu_ty != "void":
+ out_java_struct.write("\t\tpublic final " + res_map.java_hu_ty + " res;\n")
+ out_java_struct.write("\t\tprivate " + human_ty + "_OK(Object _dummy, long ptr) {\n")
+ out_java_struct.write("\t\t\tsuper(_dummy, ptr);\n")
+ if res_map.java_hu_ty == "void":
+ pass
+ elif res_map.to_hu_conv is not None:
+ out_java_struct.write("\t\t\t" + res_map.java_ty + " res = bindings." + struct_name + "_get_ok(ptr);\n")
+ out_java_struct.write("\t\t\t" + res_map.to_hu_conv.replace("\n", "\n\t\t\t"))
+ out_java_struct.write("\n\t\t\tthis.res = " + res_map.to_hu_conv_name + ";\n")
+ else:
+ out_java_struct.write("\t\t\tthis.res = bindings." + struct_name + "_get_ok(ptr);\n")
+ out_java_struct.write("\t\t}\n")
+ if struct_name.startswith("LDKCResult_None"):
+ out_java_struct.write("\t\tpublic " + human_ty + "_OK() {\n\t\t\tthis(null, bindings.C" + human_ty + "_ok());\n")
+ else:
+ out_java_struct.write("\t\tpublic " + human_ty + "_OK(" + res_map.java_hu_ty + " res) {\n")
+ if res_map.from_hu_conv is not None:
+ out_java_struct.write("\t\t\tthis(null, bindings.C" + human_ty + "_ok(" + res_map.from_hu_conv[0] + "));\n")
+ if res_map.from_hu_conv[1] != "":
+ out_java_struct.write("\t\t\t" + res_map.from_hu_conv[1] + ";\n")
+ else:
+ out_java_struct.write("\t\t\tthis(null, bindings.C" + human_ty + "_ok(res));\n")
+ out_java_struct.write("\t\t}\n\t}\n\n")
+
+ out_java.write("\tpublic static native " + err_map.java_ty + " " + struct_name + "_get_err(long arg);\n")
+ write_c(consts.c_fn_ty_pfx + err_map.c_ty + " " + consts.c_fn_name_pfx + struct_name.replace("_", "_1") + "_1get_1err (" + consts.c_fn_args_pfx + ", " + consts.ptr_c_ty + " arg) {\n")
+ write_c("\t" + struct_name + " *val = (" + struct_name + "*)arg;\n")
+ write_c("\tCHECK(!val->result_ok);\n\t")
+ out_java_struct.write("\tpublic static final class " + human_ty + "_Err extends " + human_ty + " {\n")
+ if err_map.ret_conv is not None:
+ write_c(err_map.ret_conv[0].replace("\n", "\n\t") + "(*val->contents.err)")
+ write_c(err_map.ret_conv[1].replace("\n", "\n\t") + "\n\treturn " + err_map.ret_conv_name)
+ else:
+ write_c("return *val->contents.err")
+ write_c(";\n}\n")
+
+ if err_map.java_hu_ty != "void":
+ out_java_struct.write("\t\tpublic final " + err_map.java_hu_ty + " err;\n")
+ out_java_struct.write("\t\tprivate " + human_ty + "_Err(Object _dummy, long ptr) {\n")
+ out_java_struct.write("\t\t\tsuper(_dummy, ptr);\n")
+ if err_map.java_hu_ty == "void":
+ pass
+ elif err_map.to_hu_conv is not None:
+ out_java_struct.write("\t\t\t" + err_map.java_ty + " err = bindings." + struct_name + "_get_err(ptr);\n")
+ out_java_struct.write("\t\t\t" + err_map.to_hu_conv.replace("\n", "\n\t\t\t"))
+ out_java_struct.write("\n\t\t\tthis.err = " + err_map.to_hu_conv_name + ";\n")
+ else:
+ out_java_struct.write("\t\t\tthis.err = bindings." + struct_name + "_get_err(ptr);\n")
+ out_java_struct.write("\t\t}\n")
+
+ if struct_name.endswith("NoneZ"):
+ out_java_struct.write("\t\tpublic " + human_ty + "_Err() {\n\t\t\tthis(null, bindings.C" + human_ty + "_err());\n")
+ else:
+ out_java_struct.write("\t\tpublic " + human_ty + "_Err(" + err_map.java_hu_ty + " err) {\n")
+ if err_map.from_hu_conv is not None:
+ out_java_struct.write("\t\t\tthis(null, bindings.C" + human_ty + "_err(" + err_map.from_hu_conv[0] + "));\n")
+ if err_map.from_hu_conv[1] != "":
+ out_java_struct.write("\t\t\t" + err_map.from_hu_conv[1] + ";\n")
+ else:
+ out_java_struct.write("\t\t\tthis(null, bindings.C" + human_ty + "_err(err));\n")
+ out_java_struct.write("\t\t}\n\t}\n}\n")
+
+ if can_clone:
+ clone_fns.add(struct_name.replace("LDK", "") + "_clone")
+ write_c("static inline " + struct_name + " " + struct_name.replace("LDK", "") + "_clone(const " + struct_name + " *orig) {\n")
+ write_c("\t" + struct_name + " res = { .result_ok = orig->result_ok };\n")
+ write_c("\tif (orig->result_ok) {\n")
+ if res_map.c_ty == "void":
+ write_c("\t\tres.contents.result = NULL;\n")
+ else:
+ if res_map.is_native_primitive:
+ write_c("\t\t" + res_map.c_ty + "* contents = MALLOC(sizeof(" + res_map.c_ty + "), \"" + res_map.c_ty + " result OK clone\");\n")
+ write_c("\t\t*contents = *orig->contents.result;\n")
+ else:
+ write_c("\t\t" + res_map.rust_obj + "* contents = MALLOC(sizeof(" + res_map.rust_obj + "), \"" + res_map.rust_obj + " result OK clone\");\n")
+ write_c("\t\t*contents = " + res_map.rust_obj.replace("LDK", "") + "_clone(orig->contents.result);\n")
+ write_c("\t\tres.contents.result = contents;\n")
+ write_c("\t} else {\n")
+ if err_map.c_ty == "void":
+ write_c("\t\tres.contents.err = NULL;\n")
+ else:
+ if err_map.is_native_primitive:
+ write_c("\t\t" + err_map.c_ty + "* contents = MALLOC(sizeof(" + err_map.c_ty + "), \"" + err_map.c_ty + " result Err clone\");\n")
+ write_c("\t\t*contents = *orig->contents.err;\n")
+ else:
+ write_c("\t\t" + err_map.rust_obj + "* contents = MALLOC(sizeof(" + err_map.rust_obj + "), \"" + err_map.rust_obj + " result Err clone\");\n")
+ write_c("\t\t*contents = " + err_map.rust_obj.replace("LDK", "") + "_clone(orig->contents.err);\n")
+ write_c("\t\tres.contents.err = contents;\n")
+ write_c("\t}\n\treturn res;\n}\n")
+
+ def map_tuple(struct_name, field_lines):
+ out_java.write("\tpublic static native long " + struct_name + "_new(")
+ write_c(consts.c_fn_ty_pfx + consts.ptr_c_ty + " " + consts.c_fn_name_pfx + struct_name.replace("_", "_1") + "_1new(" + consts.c_fn_args_pfx)
+ ty_list = []
+ for idx, line in enumerate(field_lines):
+ if idx != 0 and idx < len(field_lines) - 2:
+ ty_info = java_c_types(line.strip(';'), None)
+ if idx != 1:
+ out_java.write(", ")
+ e = chr(ord('a') + idx - 1)
+ out_java.write(ty_info.java_ty + " " + e)
+ write_c(", " + ty_info.c_ty + " " + e)
+ ty_list.append(ty_info)
+ tuple_types[struct_name] = (ty_list, struct_name)
+ out_java.write(");\n")
+ write_c(") {\n")
+ write_c("\t" + struct_name + "* ret = MALLOC(sizeof(" + struct_name + "), \"" + struct_name + "\");\n")
+ can_clone = True
+ clone_str = "static inline " + struct_name + " " + struct_name.replace("LDK", "") + "_clone(const " + struct_name + " *orig) {\n"
+ clone_str = clone_str + "\t" + struct_name + " ret = {\n"
+ for idx, line in enumerate(field_lines):
+ if idx != 0 and idx < len(field_lines) - 2:
+ ty_info = type_mapping_generator.map_type(line.strip(';'), False, None, False, False)
+ e = chr(ord('a') + idx - 1)
+ if ty_info.arg_conv is not None:
+ write_c("\t" + ty_info.arg_conv.replace("\n", "\n\t"))
+ write_c("\n\tret->" + e + " = " + ty_info.arg_conv_name + ";\n")
+ else:
+ write_c("\tret->" + e + " = " + e + ";\n")
+ if ty_info.arg_conv_cleanup is not None:
+ write_c("\t//TODO: Really need to call " + ty_info.arg_conv_cleanup + " here\n")
+ if not ty_info.is_native_primitive and (ty_info.rust_obj.replace("LDK", "") + "_clone") not in clone_fns:
+ can_clone = False
+ elif can_clone and ty_info.is_native_primitive:
+ clone_str = clone_str + "\t\t." + chr(ord('a') + idx - 1) + " = orig->" + chr(ord('a') + idx - 1) + ",\n"
+ elif can_clone:
+ clone_str = clone_str + "\t\t." + chr(ord('a') + idx - 1) + " = " + ty_info.rust_obj.replace("LDK", "") + "_clone(&orig->" + chr(ord('a') + idx - 1) + "),\n"
+ write_c("\treturn (long)ret;\n")
+ write_c("}\n")
+
+ if can_clone:
+ clone_fns.add(struct_name.replace("LDK", "") + "_clone")
+ write_c(clone_str)
+ write_c("\t};\n\treturn ret;\n}\n")
+
+ for idx, ty_info in enumerate(ty_list):
+ e = chr(ord('a') + idx)
+ out_java.write("\tpublic static native " + ty_info.java_ty + " " + struct_name + "_get_" + e + "(long ptr);\n")
+ write_c(consts.c_fn_ty_pfx + ty_info.c_ty + " " + consts.c_fn_name_pfx + struct_name.replace("_", "_1") + "_1get_1" + e + "(" + consts.c_fn_args_pfx + ", " + consts.ptr_c_ty + " ptr) {\n")
+ write_c("\t" + struct_name + " *tuple = (" + struct_name + "*)ptr;\n")
+ conv_info = type_mapping_generator.map_type_with_info(ty_info, False, None, False, True)
+ if conv_info.ret_conv is not None:
+ write_c("\t" + conv_info.ret_conv[0].replace("\n", "\n\t") + "tuple->" + e + conv_info.ret_conv[1].replace("\n", "\n\t") + "\n")
+ write_c("\treturn " + conv_info.ret_conv_name + ";\n")
+ else:
+ write_c("\treturn tuple->" + e + ";\n")
+ write_c("}\n")
+
+ out_java.write(consts.bindings_header)
+
+ with open(f"{sys.argv[3]}/structs/CommonBase{consts.file_ext}", "w") as out_java_struct:
+ out_java_struct.write(consts.common_base)