5 print("USAGE: /path/to/lightning.h /path/to/bindings/output.java /path/to/bindings/output.c")
8 with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java, open(sys.argv[3], "w") as out_c:
9 var_is_arr_regex = re.compile("\(\*([A-za-z_]*)\)\[([0-9]*)\]")
10 var_ty_regex = re.compile("([A-za-z_0-9]*)(.*)")
11 def map_type(fn_arg, print_void, ret_arr_len):
12 fn_arg = fn_arg.strip()
13 if fn_arg.startswith("MUST_USE_RES "):
15 if fn_arg.startswith("const "):
20 if fn_arg.startswith("void"):
22 out_java.write("void")
25 return (None, None, None)
26 fn_arg = fn_arg.strip("void ")
27 elif fn_arg.startswith("bool"):
28 out_java.write("boolean")
30 fn_arg = fn_arg.strip("bool ")
31 elif fn_arg.startswith("uint8_t"):
32 out_java.write("byte")
34 fn_arg = fn_arg.strip("uint8_t ")
35 elif fn_arg.startswith("uint32_t"):
38 fn_arg = fn_arg.strip("uint32_t ")
39 elif fn_arg.startswith("uint64_t"):
40 out_java.write("long")
42 fn_arg = fn_arg.strip("uint64_t ")
44 ma = var_ty_regex.match(fn_arg)
45 out_java.write("long")
47 is_ptr_to_obj = ma.group(1)
52 var_is_arr = var_is_arr_regex.match(fn_arg)
53 no_ptr = fn_arg.replace('*', '')
54 if var_is_arr is not None or ret_arr_len is not None:
57 if var_is_arr is not None:
58 arr_name = var_is_arr.group(1)
59 arr_len = var_is_arr.group(2)
60 out_java.write(arr_name)
65 assert(c_ty == "jbyte")
66 return ("unsigned char " + arr_name + "_arr[" + arr_len + "];\n" +
67 "(*_env)->GetByteArrayRegion (_env, """ + arr_name + ", 0, " + arr_len + ", " + arr_name + "_arr);\n" +
68 "unsigned char (*""" + arr_name + "_ref)[" + arr_len + "] = &" + arr_name + "_arr;",
69 (c_ty + "Array " + arr_name + "_arr = (*_env)->NewByteArray(_env, 0); // XXX: len 0\n" +
70 "(*_env)->SetByteArrayRegion(_env, " + arr_name + "_arr, 0, " + arr_len + ", *",
71 ");\nreturn ret_arr;"),
73 elif no_ptr.strip() != "":
74 # If we have a parameter name, print it (noting that it may indicate its a pointer)
75 out_java.write(" " + no_ptr.strip())
76 out_c.write(" " + no_ptr.strip())
77 if is_ptr_to_obj is not None:
79 return (is_ptr_to_obj + " " + no_ptr.strip() + "_conv = *(" + is_ptr_to_obj + "*)" + no_ptr.strip() + ";",
80 "XXX2", no_ptr.strip() + "_conv")
82 return (is_ptr_to_obj + "* " + no_ptr.strip() + "_conv = (" + is_ptr_to_obj + "*)" + no_ptr.strip() + ";",
83 "XXX2", no_ptr.strip() + "_conv")
84 elif no_ptr != fn_arg:
85 return ("YYY1", "XXX3", no_ptr.strip())
87 return (None, "XXX4", no_ptr.strip())
89 # We don't have a parameter name, and want one, just call it arg
90 out_java.write(" arg")
92 if is_ptr_to_obj is not None:
93 return (is_ptr_to_obj + " arg_conv = *(" + is_ptr_to_obj + "*)arg;", "XXX2", "arg_conv")
95 return (None, "XXX6", "arg")
97 # We don't have a parameter name, and don't want one (cause we're returning)
98 if is_ptr_to_obj is not None:
100 return (None, (is_ptr_to_obj + "* ret = malloc(sizeof(" + is_ptr_to_obj + "));\n*ret = ", ";\nreturn (long)ret;"), None)
102 return (None, ("return (long) ", ";"), None)
104 return (None, None, None)
106 def map_fn_args(fn_args, f):
107 for idx, arg in enumerate(fn_args.split(',')):
114 def map_fn(re_match, ret_arr_len):
115 out_java.write("\t/// " + line)
116 out_java.write("\tpublic static native ")
117 out_c.write("JNIEXPORT ")
119 _, ret_conv, _ = map_type(re_match.group(1), True, ret_arr_len)
120 if ret_conv is not None:
121 ret_conv_pfx, ret_conv_sfx = ret_conv
123 out_java.write(" " + re_match.group(2) + "(")
124 out_c.write(" JNICALL " + re_match.group(2).replace('_', '_1') + "(JNIEnv * _env, jclass _b")
127 for idx, arg in enumerate(re_match.group(3).split(',')):
132 arg_names.append(map_type(arg, False, None))
134 out_java.write(");\n")
137 for arg_conv, _, _ in arg_names:
138 if arg_conv is not None:
139 out_c.write("\t" + arg_conv.replace('\n', "\n\t") + "\n");
141 if ret_conv is not None:
142 out_c.write("\t" + ret_conv_pfx.replace('\n', '\n\t'));
144 out_c.write("\treturn ");
146 out_c.write(re_match.group(2) + "(")
147 for idx, (_, _, arg) in enumerate(arg_names):
153 if ret_conv is not None:
154 out_c.write(ret_conv_sfx.replace('\n', '\n\t'))
157 out_c.write("\n}\n\n")
159 out_java.write("""package org.ldk;
161 public class bindings {
163 System.loadLibrary(\"lightningjni\");
167 out_c.write("#include \"org_ldk_bindings.h\"\n")
168 out_c.write("#include <rust_types.h>\n\n")
169 out_c.write("#include <lightning.h>\n\n")
171 in_block_comment = False
172 in_block_enum = False
173 cur_block_struct = None
174 in_block_union = False
176 fn_ptr_regex = re.compile("^extern const ([A-Za-z_0-9\* ]*) \(\*(.*)\)\((.*)\);$")
177 fn_ret_arr_regex = re.compile("(.*) \(\*(.*)\((.*)\)\)\[([0-9]*)\];$")
178 reg_fn_regex = re.compile("([A-Za-z_0-9\* ]* \*?)([a-zA-Z_0-9]*)\((.*)\);$")
179 const_val_regex = re.compile("^extern const ([A-Za-z_0-9]*) ([A-Za-z_0-9]*);$")
183 #out_java.write("\t" + line)
184 if line.endswith("*/\n"):
185 in_block_comment = False
186 elif cur_block_struct is not None:
187 cur_block_struct = cur_block_struct + line
188 if line.startswith("} "):
190 struct_lines = cur_block_struct.split("\n")
191 for idx, struct_line in enumerate(struct_lines):
192 if struct_line.strip().startswith("/*"):
193 in_block_comment = True
195 if struct_line.endswith("*/"):
196 in_block_comment = False
198 field_lines.append(struct_line)
199 #out_java.write("".join(field_lines) + "\n")
200 cur_block_struct = None
202 if line.startswith("} "):
203 in_block_union = False
205 if line.startswith("} "):
206 in_block_enum = False
208 fn_ptr = fn_ptr_regex.match(line)
209 fn_ret_arr = fn_ret_arr_regex.match(line)
210 reg_fn = reg_fn_regex.match(line)
211 const_val = const_val_regex.match(line)
213 if line.startswith("#include <"):
215 elif line.startswith("/*"):
216 #out_java.write("\t" + line)
217 if not line.endswith("*/\n"):
218 in_block_comment = True
219 elif line.startswith("typedef enum "):
221 elif line.startswith("typedef struct "):
222 cur_block_struct = line
223 elif line.startswith("typedef union "):
224 in_block_union = True
225 elif line.startswith("typedef "):
227 elif fn_ptr is not None:
229 elif fn_ret_arr is not None:
230 map_fn(fn_ret_arr, fn_ret_arr.group(4))
231 elif reg_fn is not None:
233 elif const_val_regex is not None:
234 # TODO Map const variables
239 out_java.write("}\n")