nandi/jolt-nativepublic Fork 0
aabacba05769796ca2b8dde03e3f925d33ba6653
Commits
Clone
git clone https://git.rickub.com/nandi/jolt-native.git
git clone ssh://git@rickub.com/nandi/jolt-native.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

jolt_main.c · 155 lines · 5.4 KBC Blame HistoryRaw
Build libvidya for the phone, and hold the glue that boots it d942053 nandi 19d ago1/*
2 * The Jolt half of the Android app: an embedded Chez runtime and the boot image
3 * built from the Jolt sources, reached from `libvidya.so`'s `android_main`.
4 *
5 * This is not the NativeActivity. On Android the activity's library must be the
6 * one holding android-activity's glue, which is `libvidya.so` — see
7 * `crates/jolt-vidya/src/android.rs`. That glue dlopens this library and calls
8 * `vidya_jolt_main`, so the entry point below is an ordinary C function rather
9 * than a `main`.
10 *
11 * Every Vidya symbol is registered with Chez explicitly. Jolt resolves a
12 * `defcfn` through Chez's foreign-entry table, and on Android nothing populates
13 * that table from the dynamic loader: the symbols live in a *different* shared
14 * object (`libvidya.so`, a DT_NEEDED of this one), which is exactly the case
15 * the loader will not answer for. Registering them by hand is what makes both
16 * ABIs — the push/pop one and the retained tree one glimmer binds — reachable.
17 */
18
19#include <stddef.h>
20#include <stdio.h>
21#include <unistd.h>
22
23#include <android/log.h>
24#include <pthread.h>
25
26#include "scheme.h"
27#include "vidya.h"
28#include "vidya_tree.h"
29
30/* The boot image, linked in as a binary blob by llvm-objcopy. */
31extern const unsigned char _binary_jolt_boot_start[];
32extern const unsigned char _binary_jolt_boot_end[];
33
34#define REGISTER_VIDYA(name) Sregister_symbol(#name, (void *)&name)
35
36static void register_vidya_api(void) {
37 /* vidya.h */
38 REGISTER_VIDYA(vidya_open);
39 REGISTER_VIDYA(vidya_close);
40 REGISTER_VIDYA(vidya_should_close);
41 REGISTER_VIDYA(vidya_set_target_fps);
42 REGISTER_VIDYA(vidya_set_mode);
43 REGISTER_VIDYA(vidya_get_mode);
44 REGISTER_VIDYA(vidya_load_font);
45 REGISTER_VIDYA(vidya_begin_frame);
46 REGISTER_VIDYA(vidya_end_frame);
47 REGISTER_VIDYA(vidya_page_begin);
48 REGISTER_VIDYA(vidya_page_end);
49 REGISTER_VIDYA(vidya_card_begin);
50 REGISTER_VIDYA(vidya_card_end);
51 REGISTER_VIDYA(vidya_gap);
52 REGISTER_VIDYA(vidya_separator);
53 REGISTER_VIDYA(vidya_title);
54 REGISTER_VIDYA(vidya_title_2);
55 REGISTER_VIDYA(vidya_body);
56 REGISTER_VIDYA(vidya_dim_label);
57 REGISTER_VIDYA(vidya_button);
58 REGISTER_VIDYA(vidya_checkbox);
59 REGISTER_VIDYA(vidya_checkbox_value);
60 REGISTER_VIDYA(vidya_status);
61 REGISTER_VIDYA(vidya_text_field);
62
63 /* vidya_tree.h */
64 REGISTER_VIDYA(vidya_tree_root);
65 REGISTER_VIDYA(vidya_node_new);
66 REGISTER_VIDYA(vidya_node_free);
67 REGISTER_VIDYA(vidya_node_exists);
68 REGISTER_VIDYA(vidya_node_set_str);
69 REGISTER_VIDYA(vidya_node_set_num);
70 REGISTER_VIDYA(vidya_node_set_bool);
71 REGISTER_VIDYA(vidya_node_clear_props);
72 REGISTER_VIDYA(vidya_node_get_str);
73 REGISTER_VIDYA(vidya_node_get_num);
74 REGISTER_VIDYA(vidya_node_get_bool);
75 REGISTER_VIDYA(vidya_node_tag);
76 REGISTER_VIDYA(vidya_node_child_count);
77 REGISTER_VIDYA(vidya_node_child_at);
78 REGISTER_VIDYA(vidya_node_append);
79 REGISTER_VIDYA(vidya_node_remove);
80 REGISTER_VIDYA(vidya_node_insert_after);
81 REGISTER_VIDYA(vidya_node_replace);
82 REGISTER_VIDYA(vidya_tree_frame);
83 REGISTER_VIDYA(vidya_tree_poll_event);
84 REGISTER_VIDYA(vidya_tree_event_node);
85 REGISTER_VIDYA(vidya_tree_event_name);
86 REGISTER_VIDYA(vidya_tree_event_text);
87 REGISTER_VIDYA(vidya_tree_event_num);
88
89 /* Neither of these paints anything; they are the platform reached through
90 the same ABI. `vidya_open_url` is the one that matters here — signing in
91 leaves for a browser and comes back. */
92 REGISTER_VIDYA(vidya_clipboard_image_png);
93 REGISTER_VIDYA(vidya_open_url);
94 REGISTER_VIDYA(vidya_pick_image);
95 REGISTER_VIDYA(vidya_picked_image);
96
97 /* Live pixels, the window's own size, and the tree dump. Nothing here is
98 Android-specific; they are on this list because the list is the whole of
99 what an application can reach on Android, and a symbol left off it is not
100 a link error but a call that fails at the moment a screen needs it. */
Register vidya_set_title, which the phone cannot call without it 726f7c6 nandi 18d ago101 REGISTER_VIDYA(vidya_set_title);
Build libvidya for the phone, and hold the glue that boots it d942053 nandi 19d ago102 REGISTER_VIDYA(vidya_frame_rgba);
103 REGISTER_VIDYA(vidya_frame_drop);
104 REGISTER_VIDYA(vidya_screen_width);
105 REGISTER_VIDYA(vidya_screen_height);
106 REGISTER_VIDYA(vidya_tree_dump);
107}
108
109/*
110 * Chez writes to stdout/stderr, which on Android goes nowhere. Pump both into
111 * logcat so a Scheme-level error is visible rather than a silent exit.
112 */
113static void *log_scheme_output(void *context) {
114 int fd = *(int *)context;
115 char buffer[1024];
116 FILE *stream = fdopen(fd, "r");
117 if (stream == NULL) return NULL;
118
119 while (fgets(buffer, sizeof(buffer), stream) != NULL) {
120 __android_log_write(ANDROID_LOG_ERROR, "VidyaJolt", buffer);
121 }
122 fclose(stream);
123 return NULL;
124}
125
126int vidya_jolt_main(void) {
127 static const char *argv[] = {"vidya", NULL};
128 int output_pipe[2];
129 pthread_t logger;
130
131 if (pipe(output_pipe) == 0) {
132 dup2(output_pipe[1], STDOUT_FILENO);
133 dup2(output_pipe[1], STDERR_FILENO);
134 close(output_pipe[1]);
135 pthread_create(&logger, NULL, log_scheme_output, &output_pipe[0]);
136 pthread_detach(logger);
137 }
138
139 __android_log_print(ANDROID_LOG_INFO, "VidyaJolt",
140 "initializing embedded Chez runtime");
141 Sscheme_init(NULL);
142 Sregister_boot_file_bytes(
143 "jolt",
144 (void *)_binary_jolt_boot_start,
145 (iptr)(_binary_jolt_boot_end - _binary_jolt_boot_start));
146 Sbuild_heap(NULL, NULL);
147 register_vidya_api();
148
149 __android_log_print(ANDROID_LOG_INFO, "VidyaJolt", "starting Jolt application");
150 int status = Sscheme_start(1, argv);
151 __android_log_print(ANDROID_LOG_ERROR, "VidyaJolt",
152 "Jolt application exited with status %d", status);
153 Sscheme_deinit();
154 return status;
155}