cj-tauri 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +113 -99
  2. package/bin/cj-tauri.js +287 -287
  3. package/cjpm.toml +63 -52
  4. package/cli/cjpm.toml +22 -22
  5. package/cli/src/doctor.cj +308 -306
  6. package/cli/src/main.cj +129 -129
  7. package/cli/src/manifest.cj +632 -558
  8. package/cli/src/manifest_test.cj +87 -0
  9. package/cli/src/project.cj +770 -770
  10. package/cli/src/resolve.cj +348 -348
  11. package/cli/src/scaffold.cj +369 -369
  12. package/cli/src/sync.cj +526 -526
  13. package/cli/src/util.cj +168 -168
  14. package/cli/templates/app/README.md +51 -48
  15. package/cli/templates/app/assets/capabilities/default.json +7 -7
  16. package/cli/templates/app/assets/ui/index.html +120 -118
  17. package/cli/templates/app/cj-tauri.toml +32 -22
  18. package/cli/templates/app/cjpm.toml +34 -34
  19. package/cli/templates/app/src/main.cj +101 -90
  20. package/cli/templates/app-react/README.md +56 -56
  21. package/cli/templates/app-react/assets/capabilities/default.json +7 -7
  22. package/cli/templates/app-react/assets/ui/index.html +25 -25
  23. package/cli/templates/app-react/assets/ui/package.json +19 -19
  24. package/cli/templates/app-react/assets/ui/src/App.css +67 -67
  25. package/cli/templates/app-react/assets/ui/src/App.jsx +124 -124
  26. package/cli/templates/app-react/assets/ui/src/main.jsx +6 -6
  27. package/cli/templates/app-react/assets/ui/vite.config.js +24 -24
  28. package/cli/templates/app-react/cj-tauri.toml +33 -23
  29. package/cli/templates/app-react/cjpm.toml +34 -34
  30. package/cli/templates/app-react/src/main.cj +91 -91
  31. package/cli/templates/app-vue/README.md +56 -56
  32. package/cli/templates/app-vue/assets/capabilities/default.json +7 -7
  33. package/cli/templates/app-vue/assets/ui/index.html +25 -25
  34. package/cli/templates/app-vue/assets/ui/package.json +18 -18
  35. package/cli/templates/app-vue/assets/ui/src/App.vue +176 -176
  36. package/cli/templates/app-vue/assets/ui/src/main.js +4 -4
  37. package/cli/templates/app-vue/assets/ui/vite.config.js +24 -24
  38. package/cli/templates/app-vue/cj-tauri.toml +33 -23
  39. package/cli/templates/app-vue/cjpm.toml +34 -34
  40. package/cli/templates/app-vue/src/main.cj +91 -91
  41. package/cli/templates/ohos-skeleton/AppScope/app.json5 +13 -13
  42. package/cli/templates/ohos-skeleton/AppScope/resources/base/element/string.json +8 -8
  43. package/cli/templates/ohos-skeleton/AppScope/resources/base/media/layered_image.json +6 -6
  44. package/cli/templates/ohos-skeleton/README.md +84 -79
  45. package/cli/templates/ohos-skeleton/build-hap.sh +15 -0
  46. package/cli/templates/ohos-skeleton/build-profile.json5 +46 -46
  47. package/cli/templates/ohos-skeleton/entry/build-profile.json5 +26 -26
  48. package/cli/templates/ohos-skeleton/entry/cjpm.toml +51 -43
  49. package/cli/templates/ohos-skeleton/entry/hvigorfile.ts +6 -6
  50. package/cli/templates/ohos-skeleton/entry/oh-package.json5 +9 -9
  51. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/ability_stage.cj +17 -17
  52. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/app_host.cj +94 -94
  53. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/dialog_host.cj +217 -0
  54. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/index.cj +527 -167
  55. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/main_ability.cj +139 -139
  56. package/cli/templates/ohos-skeleton/entry/src/main/module.json5 +57 -49
  57. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/color.json +8 -8
  58. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/string.json +16 -16
  59. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/media/layered_image.json +6 -6
  60. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/profile/main_pages.json +2 -2
  61. package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/capabilities.json +6 -6
  62. package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/index.html +92 -92
  63. package/cli/templates/ohos-skeleton/hvigor/hvigor-config.json5 +5 -5
  64. package/cli/templates/ohos-skeleton/hvigorfile.ts +6 -6
  65. package/cli/templates/ohos-skeleton/oh-package.json5 +10 -10
  66. package/native/build_win.bat +62 -62
  67. package/native/core/bridge_core.c +1681 -1626
  68. package/native/core/bridge_core.h +675 -618
  69. package/native/core/bridge_js.h +108 -108
  70. package/native/platforms/harmonyos/README.md +115 -6
  71. package/native/platforms/linux/bridge_linux.c +2787 -2485
  72. package/native/platforms/windows/bridge_win.c +3740 -3248
  73. package/native/tests/gtk_threading_probe.c +143 -143
  74. package/native/tests/test_bridge_core.c +1339 -1228
  75. package/package.json +53 -53
  76. package/prebuilt/linux-x64/cj-tauri +0 -0
  77. package/src/api_system.cj +67 -67
  78. package/src/app.cj +325 -969
  79. package/src/app_events.cj +166 -0
  80. package/src/app_host_ops.cj +287 -0
  81. package/src/app_run.cj +283 -0
  82. package/src/app_spec.cj +76 -76
  83. package/src/arkweb_menu.cj +216 -0
  84. package/src/arkweb_script.cj +142 -142
  85. package/src/capability.cj +409 -409
  86. package/src/clipboard_bridge.cj +178 -0
  87. package/src/dialog_spec.cj +79 -0
  88. package/src/dragdrop.cj +26 -26
  89. package/src/embedded_assets.cj +98 -98
  90. package/src/host.cj +752 -607
  91. package/src/host_arkweb.cj +924 -778
  92. package/src/host_webkit.cj +663 -570
  93. package/src/host_webview2.cj +663 -570
  94. package/src/hotkey.cj +66 -66
  95. package/src/ipc_hub.cj +337 -337
  96. package/src/ipc_message.cj +286 -286
  97. package/src/launch.cj +62 -62
  98. package/src/logging.cj +127 -127
  99. package/src/menu.cj +197 -197
  100. package/src/platform/platform_app_context.cj +77 -77
  101. package/src/platform/platform_assets.cj +33 -33
  102. package/src/platform/platform_discover.cj +176 -176
  103. package/src/platform/platform_env.cj +29 -29
  104. package/src/platform/platform_feature.cj +31 -31
  105. package/src/platform/platform_page_source.cj +87 -87
  106. package/src/platform/platform_target_info.cj +32 -32
  107. package/src/platform_host_provider.cj +87 -87
  108. package/src/plugin.cj +333 -333
  109. package/src/plugins/clipboard/plugin_clipboard.cj +152 -152
  110. package/src/plugins/dialog/plugin_dialog.cj +209 -209
  111. package/src/plugins/fs/plugin_fs.cj +105 -1
  112. package/src/plugins/http/http_backend.cj +131 -0
  113. package/src/plugins/http/http_desktop.cj +195 -0
  114. package/src/plugins/http/http_ohos.cj +204 -0
  115. package/src/plugins/http/plugin_http.cj +310 -459
  116. package/src/plugins/log/plugin_log.cj +105 -105
  117. package/src/plugins/menu/plugin_menu.cj +158 -158
  118. package/src/plugins/notification/plugin_notification.cj +154 -154
  119. package/src/plugins/serial/plugin_serial.cj +458 -454
  120. package/src/plugins/serial/serial_bridge.cj +194 -194
  121. package/src/plugins/serial/serial_manager_ohos.cj +92 -0
  122. package/src/plugins/serial/serial_ohos.cj +529 -0
  123. package/src/plugins/shell/plugin_shell.cj +258 -258
  124. package/src/plugins/sqlite/plugin_sqlite.cj +705 -710
  125. package/src/plugins/sqlite/sqlite_ffi.cj +206 -211
  126. package/src/plugins/ws/plugin_ws.cj +488 -470
  127. package/src/process_hidden.cj +174 -174
  128. package/src/scope.cj +391 -391
  129. package/src/shell_event.cj +69 -69
  130. package/src/tests/app_spec_test.cj +126 -127
  131. package/src/tests/capability_test.cj +243 -243
  132. package/src/tests/dialog_spec_test.cj +73 -0
  133. package/src/tests/fake_host.cj +201 -201
  134. package/src/tests/ipc_hub_test.cj +487 -487
  135. package/src/tests/logging_test.cj +62 -62
  136. package/src/tests/platform_contract_test.cj +251 -251
  137. package/src/tests/plugin_clipboard_test.cj +222 -222
  138. package/src/tests/plugin_dialog_test.cj +237 -237
  139. package/src/tests/plugin_fs_test.cj +207 -0
  140. package/src/tests/plugin_http_test.cj +124 -124
  141. package/src/tests/plugin_notification_test.cj +205 -205
  142. package/src/tests/plugin_serial_test.cj +48 -0
  143. package/src/tests/plugin_test.cj +605 -585
  144. package/src/tests/plugin_ws_test.cj +40 -40
  145. package/src/tests/process_hidden_test.cj +129 -129
  146. package/src/tests/scope_test.cj +350 -350
  147. package/src/tests/system_host_test.cj +99 -81
  148. package/src/tests/urlutil_test.cj +53 -53
  149. package/src/tests/version_test.cj +75 -75
  150. package/src/tests/window_registry_test.cj +123 -123
  151. package/src/tray.cj +90 -90
  152. package/src/urlutil.cj +159 -159
  153. package/src/version.cj +44 -44
  154. package/src/window.cj +51 -51
  155. package/src/window_registry.cj +116 -116
  156. package/prebuilt/win32-x64/cj-tauri.exe +0 -0
  157. package/src/plugins/serial/serial_ohos_stub.cj +0 -61
  158. package/src/plugins/sqlite/sqlite_ohos_stub.cj +0 -91
@@ -1,174 +1,174 @@
1
- package cjTauri
2
-
3
- /**
4
- * 后台(静默)子进程:起一个**控制台程序**,但不要那个控制台窗口。
5
- *
6
- * 为什么需要它:cj-tauri 的应用产物是 GUI 子系统(Windows 的 `--subsystem=windows`),父进程
7
- * 没有控制台;此时用 `std.process.launch` 拉起一个**控制台子系统**的程序(cjh、ffmpeg 这类 CLI),
8
- * Windows 会给子进程单独配一个控制台窗口——用户看到的就是「点了一下,旁边蹦出一个黑窗口」。
9
- * `std.process.launch` 的签名里没有可以传创建标志的地方,所以这条下沉到 C 桥
10
- * (平台差异只允许出现在 `@When` 与 `bridge_*.c`,AGENTS §2):
11
- * Windows = `CreateProcessW` + `DETACHED_PROCESS`(子进程**根本没有** console:`CREATE_NO_WINDOW`
12
- * 只是不显示窗口,它仍持有一个隐藏 console、conhost 照挂;三个标准句柄显式指到 NUL,否则子进程一
13
- * println 就可能死在自己的控制台上),Linux = `posix_spawn` + 自成会话(终端 Ctrl-C 不连带打死)。
14
- *
15
- * 与 `std.process.launch` 的取舍:这条**拿不到子进程的 stdout / stderr**(Windows 指向 NUL、
16
- * Linux 指向 /dev/null)。要读它的输出就别用这个——那需要管道,是另一件事。
17
- *
18
- * 句柄口径:只留 pid(Windows 的进程句柄当场关掉,不占句柄表;Linux 的子进程是分离的,
19
- * 父进程退出后它照样活着)。要让它结束就 `stop()`,要判它还在不在就 `isAlive()`。
20
- */
21
- public class BackgroundProcess {
22
- private let pid: Int64
23
-
24
- init(pid: Int64) {
25
- this.pid = pid
26
- }
27
-
28
- /** 进程号(恒 > 0:拿到它的路径只有 `launchHidden` 成功那一条) */
29
- public func processId(): Int64 {
30
- return pid
31
- }
32
-
33
- /** 还在跑吗(查不到即按「不在」上报——调用方据此决定要不要重新拉起) */
34
- public func isAlive(): Bool {
35
- return hiddenPidAlive(pid)
36
- }
37
-
38
- /**
39
- * 让它结束:先按正常终止(Windows = TerminateProcess;Linux = SIGTERM,3 秒不走再 SIGKILL)。
40
- * 幂等——进程已经不在了也算成功。
41
- */
42
- public func stop(): Unit {
43
- if (!hiddenPidKill(pid)) {
44
- eprintln("[cj-tauri] 终止子进程失败(pid=${pid})")
45
- }
46
- }
47
- }
48
-
49
- /**
50
- * 静默启动一个后台进程:`exePath` 是程序路径,`args` 是参数表(**不要自己加引号**,
51
- * 空格 / 引号由平台按各自规则转义)。
52
- *
53
- * 返回 `None` 的三种情况:路径为空、参数里混进了内部分隔符(0x1F)、平台起不来进程
54
- * (原因已由 C 桥打进 stderr)。**绝不在没起进程时返回一个 pid**。
55
- *
56
- * 典型用法(应用侧 AI 后端:随包的 cjh):
57
- *
58
- * ```cangjie
59
- * match (launchHidden(bin, ["web", "--port", "8765"])) {
60
- * case Some(p) => backendPid = p.processId()
61
- * case None => eprintln("[app] 后端没起来")
62
- * }
63
- * ```
64
- */
65
- public func launchHidden(exePath: String, args: Array<String>): Option<BackgroundProcess> {
66
- if (exePath.isEmpty()) {
67
- eprintln("[cj-tauri] launchHidden: 程序路径为空")
68
- return None
69
- }
70
- let wire = match (joinHiddenArgs(args)) {
71
- case Some(w) => w
72
- case None => return None
73
- }
74
- let pid = spawnHiddenPid(exePath, wire)
75
- if (pid <= 0) {
76
- return None
77
- }
78
- return Some(BackgroundProcess(pid))
79
- }
80
-
81
- /**
82
- * 把参数表拼成 C 桥认的「线格式」:按 0x1F(单元分隔符)连接,由平台侧再切成 argv。
83
- *
84
- * 这个字节不会出现在正常参数里,所以一旦出现就**当场拒绝**(`None`)——默默拼错比拒绝更糟:
85
- * 参数被劈成两个、而调用方拿到的是「启动成功」。
86
- *
87
- * 抽成纯函数是为了单测:真正难的不是拼接,是「拼出来还能不能原样切开」这条不变量
88
- * (`src/tests/process_hidden_test.cj`)。
89
- */
90
- public func joinHiddenArgs(args: Array<String>): Option<String> {
91
- let sep = "\u{1F}"
92
- var wire = ""
93
- var first = true
94
- for (a in args) {
95
- if (let Some(_) <- a.indexOf(sep)) {
96
- eprintln("[cj-tauri] launchHidden: 参数里不允许出现 0x1F 分隔符(${a})")
97
- return None
98
- }
99
- if (!first) {
100
- wire += sep
101
- }
102
- wire += a
103
- first = false
104
- }
105
- return Some(wire)
106
- }
107
-
108
- /**
109
- * 静默启动的 C 桥出口:成功回 pid(> 0),失败回 0(平台已把原因写进 stderr)。
110
- *
111
- * 鸿蒙侧没有 C 桥产物(`native/platforms/harmonyos/` 目前只有契约),照桌面那份写会让模块
112
- * 加载期就 SIGSEGV(与 `log_bridge.cj` 同一条坑,AGENTS §4)——所以按 `env` 分叉,如实降级。
113
- * 判据用 `env` 而不是 `arch`:桌面 aarch64 Linux 也有 C 桥。
114
- */
115
- @When[env != "ohos"]
116
- @C
117
- foreign func cj_bridge_spawn_hidden(exe: CString, args: CString): Int64
118
-
119
- /** 终止 pid(幂等);鸿蒙侧无桥,不用声明。 */
120
- @When[env != "ohos"]
121
- @C
122
- foreign func cj_bridge_kill_pid(pid: Int64): Int32
123
-
124
- /** 探活(1 = 活着);鸿蒙侧无桥,不用声明。 */
125
- @When[env != "ohos"]
126
- @C
127
- foreign func cj_bridge_pid_alive(pid: Int64): Int32
128
-
129
- @When[env != "ohos"]
130
- func spawnHiddenPid(exePath: String, argsWire: String): Int64 {
131
- var pid: Int64 = 0
132
- unsafe {
133
- pid = cj_bridge_spawn_hidden(LibC.mallocCString(exePath), LibC.mallocCString(argsWire))
134
- }
135
- return pid
136
- }
137
-
138
- /** 鸿蒙侧:没有桥就没有后台静默启动,如实报 0 并说清代价(用 std.process.launch 会带出控制台) */
139
- @When[env == "ohos"]
140
- func spawnHiddenPid(exePath: String, argsWire: String): Int64 {
141
- let _ = argsWire
142
- eprintln("[cj-tauri] 本平台没有 C 桥,无法后台静默启动:${exePath}")
143
- return 0
144
- }
145
-
146
- @When[env != "ohos"]
147
- func hiddenPidAlive(pid: Int64): Bool {
148
- var alive: Int32 = 0
149
- unsafe {
150
- alive = cj_bridge_pid_alive(pid)
151
- }
152
- return alive == 1
153
- }
154
-
155
- @When[env == "ohos"]
156
- func hiddenPidAlive(pid: Int64): Bool {
157
- let _ = pid
158
- return false
159
- }
160
-
161
- @When[env != "ohos"]
162
- func hiddenPidKill(pid: Int64): Bool {
163
- var rc: Int32 = 0
164
- unsafe {
165
- rc = cj_bridge_kill_pid(pid)
166
- }
167
- return rc == 1
168
- }
169
-
170
- @When[env == "ohos"]
171
- func hiddenPidKill(pid: Int64): Bool {
172
- let _ = pid
173
- return false
174
- }
1
+ package cjTauri
2
+
3
+ /**
4
+ * 后台(静默)子进程:起一个**控制台程序**,但不要那个控制台窗口。
5
+ *
6
+ * 为什么需要它:cj-tauri 的应用产物是 GUI 子系统(Windows 的 `--subsystem=windows`),父进程
7
+ * 没有控制台;此时用 `std.process.launch` 拉起一个**控制台子系统**的程序(cjh、ffmpeg 这类 CLI),
8
+ * Windows 会给子进程单独配一个控制台窗口——用户看到的就是「点了一下,旁边蹦出一个黑窗口」。
9
+ * `std.process.launch` 的签名里没有可以传创建标志的地方,所以这条下沉到 C 桥
10
+ * (平台差异只允许出现在 `@When` 与 `bridge_*.c`,AGENTS §2):
11
+ * Windows = `CreateProcessW` + `DETACHED_PROCESS`(子进程**根本没有** console:`CREATE_NO_WINDOW`
12
+ * 只是不显示窗口,它仍持有一个隐藏 console、conhost 照挂;三个标准句柄显式指到 NUL,否则子进程一
13
+ * println 就可能死在自己的控制台上),Linux = `posix_spawn` + 自成会话(终端 Ctrl-C 不连带打死)。
14
+ *
15
+ * 与 `std.process.launch` 的取舍:这条**拿不到子进程的 stdout / stderr**(Windows 指向 NUL、
16
+ * Linux 指向 /dev/null)。要读它的输出就别用这个——那需要管道,是另一件事。
17
+ *
18
+ * 句柄口径:只留 pid(Windows 的进程句柄当场关掉,不占句柄表;Linux 的子进程是分离的,
19
+ * 父进程退出后它照样活着)。要让它结束就 `stop()`,要判它还在不在就 `isAlive()`。
20
+ */
21
+ public class BackgroundProcess {
22
+ private let pid: Int64
23
+
24
+ init(pid: Int64) {
25
+ this.pid = pid
26
+ }
27
+
28
+ /** 进程号(恒 > 0:拿到它的路径只有 `launchHidden` 成功那一条) */
29
+ public func processId(): Int64 {
30
+ return pid
31
+ }
32
+
33
+ /** 还在跑吗(查不到即按「不在」上报——调用方据此决定要不要重新拉起) */
34
+ public func isAlive(): Bool {
35
+ return hiddenPidAlive(pid)
36
+ }
37
+
38
+ /**
39
+ * 让它结束:先按正常终止(Windows = TerminateProcess;Linux = SIGTERM,3 秒不走再 SIGKILL)。
40
+ * 幂等——进程已经不在了也算成功。
41
+ */
42
+ public func stop(): Unit {
43
+ if (!hiddenPidKill(pid)) {
44
+ eprintln("[cj-tauri] 终止子进程失败(pid=${pid})")
45
+ }
46
+ }
47
+ }
48
+
49
+ /**
50
+ * 静默启动一个后台进程:`exePath` 是程序路径,`args` 是参数表(**不要自己加引号**,
51
+ * 空格 / 引号由平台按各自规则转义)。
52
+ *
53
+ * 返回 `None` 的三种情况:路径为空、参数里混进了内部分隔符(0x1F)、平台起不来进程
54
+ * (原因已由 C 桥打进 stderr)。**绝不在没起进程时返回一个 pid**。
55
+ *
56
+ * 典型用法(应用侧 AI 后端:随包的 cjh):
57
+ *
58
+ * ```cangjie
59
+ * match (launchHidden(bin, ["web", "--port", "8765"])) {
60
+ * case Some(p) => backendPid = p.processId()
61
+ * case None => eprintln("[app] 后端没起来")
62
+ * }
63
+ * ```
64
+ */
65
+ public func launchHidden(exePath: String, args: Array<String>): Option<BackgroundProcess> {
66
+ if (exePath.isEmpty()) {
67
+ eprintln("[cj-tauri] launchHidden: 程序路径为空")
68
+ return None
69
+ }
70
+ let wire = match (joinHiddenArgs(args)) {
71
+ case Some(w) => w
72
+ case None => return None
73
+ }
74
+ let pid = spawnHiddenPid(exePath, wire)
75
+ if (pid <= 0) {
76
+ return None
77
+ }
78
+ return Some(BackgroundProcess(pid))
79
+ }
80
+
81
+ /**
82
+ * 把参数表拼成 C 桥认的「线格式」:按 0x1F(单元分隔符)连接,由平台侧再切成 argv。
83
+ *
84
+ * 这个字节不会出现在正常参数里,所以一旦出现就**当场拒绝**(`None`)——默默拼错比拒绝更糟:
85
+ * 参数被劈成两个、而调用方拿到的是「启动成功」。
86
+ *
87
+ * 抽成纯函数是为了单测:真正难的不是拼接,是「拼出来还能不能原样切开」这条不变量
88
+ * (`src/tests/process_hidden_test.cj`)。
89
+ */
90
+ public func joinHiddenArgs(args: Array<String>): Option<String> {
91
+ let sep = "\u{1F}"
92
+ var wire = ""
93
+ var first = true
94
+ for (a in args) {
95
+ if (let Some(_) <- a.indexOf(sep)) {
96
+ eprintln("[cj-tauri] launchHidden: 参数里不允许出现 0x1F 分隔符(${a})")
97
+ return None
98
+ }
99
+ if (!first) {
100
+ wire += sep
101
+ }
102
+ wire += a
103
+ first = false
104
+ }
105
+ return Some(wire)
106
+ }
107
+
108
+ /**
109
+ * 静默启动的 C 桥出口:成功回 pid(> 0),失败回 0(平台已把原因写进 stderr)。
110
+ *
111
+ * 鸿蒙侧没有 C 桥产物(`native/platforms/harmonyos/` 目前只有契约),照桌面那份写会让模块
112
+ * 加载期就 SIGSEGV(与 `log_bridge.cj` 同一条坑,AGENTS §4)——所以按 `env` 分叉,如实降级。
113
+ * 判据用 `env` 而不是 `arch`:桌面 aarch64 Linux 也有 C 桥。
114
+ */
115
+ @When[env != "ohos"]
116
+ @C
117
+ foreign func cj_bridge_spawn_hidden(exe: CString, args: CString): Int64
118
+
119
+ /** 终止 pid(幂等);鸿蒙侧无桥,不用声明。 */
120
+ @When[env != "ohos"]
121
+ @C
122
+ foreign func cj_bridge_kill_pid(pid: Int64): Int32
123
+
124
+ /** 探活(1 = 活着);鸿蒙侧无桥,不用声明。 */
125
+ @When[env != "ohos"]
126
+ @C
127
+ foreign func cj_bridge_pid_alive(pid: Int64): Int32
128
+
129
+ @When[env != "ohos"]
130
+ func spawnHiddenPid(exePath: String, argsWire: String): Int64 {
131
+ var pid: Int64 = 0
132
+ unsafe {
133
+ pid = cj_bridge_spawn_hidden(LibC.mallocCString(exePath), LibC.mallocCString(argsWire))
134
+ }
135
+ return pid
136
+ }
137
+
138
+ /** 鸿蒙侧:没有桥就没有后台静默启动,如实报 0 并说清代价(用 std.process.launch 会带出控制台) */
139
+ @When[env == "ohos"]
140
+ func spawnHiddenPid(exePath: String, argsWire: String): Int64 {
141
+ let _ = argsWire
142
+ eprintln("[cj-tauri] 本平台没有 C 桥,无法后台静默启动:${exePath}")
143
+ return 0
144
+ }
145
+
146
+ @When[env != "ohos"]
147
+ func hiddenPidAlive(pid: Int64): Bool {
148
+ var alive: Int32 = 0
149
+ unsafe {
150
+ alive = cj_bridge_pid_alive(pid)
151
+ }
152
+ return alive == 1
153
+ }
154
+
155
+ @When[env == "ohos"]
156
+ func hiddenPidAlive(pid: Int64): Bool {
157
+ let _ = pid
158
+ return false
159
+ }
160
+
161
+ @When[env != "ohos"]
162
+ func hiddenPidKill(pid: Int64): Bool {
163
+ var rc: Int32 = 0
164
+ unsafe {
165
+ rc = cj_bridge_kill_pid(pid)
166
+ }
167
+ return rc == 1
168
+ }
169
+
170
+ @When[env == "ohos"]
171
+ func hiddenPidKill(pid: Int64): Bool {
172
+ let _ = pid
173
+ return false
174
+ }