Skip to main content

msime_engine_capi/
lib.rs

1// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
2
3//! 水杉输入法引擎的 C ABI:把核心层 `msime_engine::Session` 包成带版本的 C 函数,符号一律以 `msime_engine_` 开头,头文件是 cbindgen 生成并提交的 `include/msime_engine.h`。
4//!
5//! 设计与取舍见 `.agents/notes/implemented/architecture/2026-10-29-engine-capi.md`,给 C 采用方的用法(生命周期、按键路由、线程、内存、要带的数据文件、许可证)见 crate 的 README。这里只包核心层,不包 `host` 门面,也不扩展 host-api。
6
7// 工作区禁止 unsafe;这个 crate 就是 C 采用方链接的边界,收进来的每个指针、长度和句柄都是编译器查不到的约定。豁免写在这里而不是退出工作区的 lint 表,和其他 FFI crate 一样,免得以后工作区加的 lint 悄悄漏掉这里。
8#![allow(unsafe_code)]
9// 类型名与 C 头文件里的一致(`msime_engine_str`),cbindgen 原样导出。
10#![allow(non_camel_case_types)]
11
12mod abi;
13mod library;
14mod options;
15mod session;
16#[cfg(test)]
17mod tests;
18
19pub use abi::{
20    msime_engine_candidate, msime_engine_paths, msime_engine_result, msime_engine_state,
21    msime_engine_str,
22};
23pub use library::*;
24pub use session::*;
25
26// ---- 版本 ----
27
28/// ABI 主版本。同一个主版本内只追加函数、常量和结构体尾部的字段,不改已有的含义;Linux 的 SONAME 带的就是它(`libmsime_engine.so.1`)。
29pub const MSIME_ENGINE_ABI_MAJOR: u32 = 1;
30/// ABI 次版本,每次追加加一。调用方可以按 `msime_engine_abi_version()` 判断运行时的库有没有某个后加的函数。
31pub const MSIME_ENGINE_ABI_MINOR: u32 = 1;
32
33// ---- 返回码 ----
34//
35// 除了 `msime_engine_abi_version`、`msime_engine_version`、`msime_engine_last_error` 和 `msime_engine_string_free`,每个函数都返回 `int32_t` 状态码。非零时 `msime_engine_last_error()` 给出说明文字。编号冻结,只追加;1、2、3、6 与引擎的 `ErrorCode` 共用一个空间。
36
37/// 成功。
38pub const MSIME_ENGINE_OK: i32 = 0;
39/// 参数不合法:选项 JSON 有未知键或取值不对、索引越界、不是 UTF-8、`struct_size` 比 1.0 的布局还小等。
40pub const MSIME_ENGINE_INVALID_ARGUMENT: i32 = 1;
41/// 引擎没能完成操作(例如换到一个没有词库的方案)。
42pub const MSIME_ENGINE_FAILED: i32 = 2;
43/// SQLite 或文件系统出错。
44pub const MSIME_ENGINE_STORAGE: i32 = 3;
45/// 这个库不认识的选项编号、模型种类或标志位。
46pub const MSIME_ENGINE_UNSUPPORTED: i32 = 4;
47/// 传入的 `revision` 不是会话当前的候选修订号:候选已经变了,先重新 `msime_engine_state_get`。
48pub const MSIME_ENGINE_STALE: i32 = 5;
49/// 会话正被另一个线程调用(同一会话的调用不能并发),或者词库正被别的会话、别的进程占着(维护要等所有会话关掉)。什么也没做,稍后重试。
50pub const MSIME_ENGINE_BUSY: i32 = 6;
51/// 之前的某次调用在库里 panic 了,会话已作废,只能 `msime_engine_session_free`。进程级函数 panic 时也返回它,但不作废任何东西。
52pub const MSIME_ENGINE_PANIC: i32 = 7;
53/// 必需的指针参数是 NULL。
54pub const MSIME_ENGINE_NULL: i32 = 8;
55
56const _: () = {
57    use msime_engine::ErrorCode;
58    assert!(ErrorCode::InvalidArgument.value() == MSIME_ENGINE_INVALID_ARGUMENT as u32);
59    assert!(ErrorCode::Failed.value() == MSIME_ENGINE_FAILED as u32);
60    assert!(ErrorCode::Storage.value() == MSIME_ENGINE_STORAGE as u32);
61    assert!(ErrorCode::Busy.value() == MSIME_ENGINE_BUSY as u32);
62};
63
64// ---- 方案(`SchemeType` 的序号,冻结) ----
65
66pub const MSIME_ENGINE_SCHEME_QUANPIN: u32 = 0;
67pub const MSIME_ENGINE_SCHEME_SHUANGPIN: u32 = 1;
68pub const MSIME_ENGINE_SCHEME_WUBI: u32 = 2;
69pub const MSIME_ENGINE_SCHEME_JAPANESE: u32 = 3;
70pub const MSIME_ENGINE_SCHEME_KOREAN: u32 = 4;
71pub const MSIME_ENGINE_SCHEME_CANTONESE: u32 = 5;
72pub const MSIME_ENGINE_SCHEME_ZHUYIN: u32 = 6;
73pub const MSIME_ENGINE_SCHEME_VIETNAMESE: u32 = 7;
74pub const MSIME_ENGINE_SCHEME_TIBETAN: u32 = 8;
75pub const MSIME_ENGINE_SCHEME_STROKE: u32 = 9;
76
77// ---- 命令(核心层 `Command` 的序号,冻结;与 host-api 的命令编号不同) ----
78
79pub const MSIME_ENGINE_COMMAND_BACKSPACE: u32 = 0;
80/// 上屏首选(引擎顺序的第 0 行)。宿主自己高亮了别的行时用 `msime_engine_select`。
81pub const MSIME_ENGINE_COMMAND_COMMIT_CANDIDATE: u32 = 1;
82/// 上屏按键原文(回车)。专用英文里打的词学进英文词库;选项 `english.learn_typed_spellings_on_enter` 打开时,临时英文的字母和拼不成音节的拼音也学。
83pub const MSIME_ENGINE_COMMAND_COMMIT_RAW: u32 = 2;
84/// 丢弃组字(Esc)。越南文和藏文的第一次只把显示切回按键原文,再发一次才丢弃;开着可打开的候选列表(韩文汉字)时第一次只关列表。
85pub const MSIME_ENGINE_COMMAND_CANCEL: u32 = 3;
86pub const MSIME_ENGINE_COMMAND_MOVE_LEFT: u32 = 4;
87pub const MSIME_ENGINE_COMMAND_MOVE_RIGHT: u32 = 5;
88pub const MSIME_ENGINE_COMMAND_MOVE_HOME: u32 = 6;
89pub const MSIME_ENGINE_COMMAND_MOVE_END: u32 = 7;
90pub const MSIME_ENGINE_COMMAND_DELETE_FORWARD: u32 = 8;
91/// 只用于日文:切换假名写法。
92pub const MSIME_ENGINE_COMMAND_CYCLE_KANA_VARIANT: u32 = 9;
93/// 只用于日文:上屏假名读音。
94pub const MSIME_ENGINE_COMMAND_COMMIT_READING: u32 = 10;
95/// 打开或关闭当前方案可打开的候选列表:韩文当前音节的汉字、注音整句的其他转换。
96pub const MSIME_ENGINE_COMMAND_OPEN_CANDIDATE_LIST: u32 = 11;
97/// 整句改字的光标左移一个字;进不了改字时与 `MOVE_LEFT` 相同。
98pub const MSIME_ENGINE_COMMAND_CONVERSION_LEFT: u32 = 12;
99/// 整句改字的光标右移一个字;不在改字里时与 `MOVE_RIGHT` 相同。
100pub const MSIME_ENGINE_COMMAND_CONVERSION_RIGHT: u32 = 13;
101/// ABI 1.1 起:与 `COMMIT_RAW` 上屏同样的原文,但不学英文词(例如宿主的 Shift+回车)。1.0 的库对它返回 `MSIME_ENGINE_UNSUPPORTED`。
102pub const MSIME_ENGINE_COMMAND_COMMIT_RAW_WITHOUT_LEARNING: u32 = 14;
103
104// ---- 候选来源(`CandidateSource` 的序号,冻结) ----
105//
106// 不进 ABI 的能力(云与 AI 候选、插件、联系人、多语言)的来源也保留编号,这个 ABI 不会产生它们;10 从未发布过。
107
108pub const MSIME_ENGINE_SOURCE_DATABASE: u32 = 0;
109pub const MSIME_ENGINE_SOURCE_USER_DATABASE: u32 = 1;
110pub const MSIME_ENGINE_SOURCE_CLOUD_SUGGESTION: u32 = 2;
111pub const MSIME_ENGINE_SOURCE_AI_SUGGESTION: u32 = 3;
112pub const MSIME_ENGINE_SOURCE_ENGLISH_DICTIONARY: u32 = 4;
113pub const MSIME_ENGINE_SOURCE_QUICK_PHRASE: u32 = 5;
114/// emoji 行,也用于打拼音出符号的符号行:选中时整段上屏,不学习。
115pub const MSIME_ENGINE_SOURCE_EMOJI: u32 = 6;
116pub const MSIME_ENGINE_SOURCE_KAOMOJI: u32 = 7;
117/// 词格解出的整句。
118pub const MSIME_ENGINE_SOURCE_GENERATED: u32 = 8;
119/// 解码器给不出词时的原文或兜底行。
120pub const MSIME_ENGINE_SOURCE_FALLBACK: u32 = 9;
121pub const MSIME_ENGINE_SOURCE_NEURAL_KEYBOARD: u32 = 11;
122pub const MSIME_ENGINE_SOURCE_AI_PENDING: u32 = 12;
123pub const MSIME_ENGINE_SOURCE_MIXED_JAPANESE: u32 = 13;
124pub const MSIME_ENGINE_SOURCE_PLUGIN: u32 = 14;
125pub const MSIME_ENGINE_SOURCE_CLOUD_PENDING: u32 = 15;
126pub const MSIME_ENGINE_SOURCE_CONTACT: u32 = 16;
127pub const MSIME_ENGINE_SOURCE_COLLOCATION: u32 = 17;
128pub const MSIME_ENGINE_SOURCE_MULTILINGUAL: u32 = 18;
129
130// ---- 本地模式(`msime_engine_state::local_mode`,冻结) ----
131
132pub const MSIME_ENGINE_LOCAL_MODE_NONE: u32 = 0;
133pub const MSIME_ENGINE_LOCAL_MODE_UNICODE: u32 = 1;
134pub const MSIME_ENGINE_LOCAL_MODE_DATE_TIME: u32 = 2;
135pub const MSIME_ENGINE_LOCAL_MODE_QUICK_PHRASE: u32 = 3;
136pub const MSIME_ENGINE_LOCAL_MODE_EMOJI: u32 = 4;
137pub const MSIME_ENGINE_LOCAL_MODE_KAOMOJI: u32 = 5;
138pub const MSIME_ENGINE_LOCAL_MODE_SUPER_JIANPIN: u32 = 6;
139pub const MSIME_ENGINE_LOCAL_MODE_TEMPORARY_ENGLISH: u32 = 7;
140pub const MSIME_ENGINE_LOCAL_MODE_TEMPORARY_JAPANESE: u32 = 8;
141pub const MSIME_ENGINE_LOCAL_MODE_EXPRESSION: u32 = 9;
142pub const MSIME_ENGINE_LOCAL_MODE_COMMAND: u32 = 10;
143pub const MSIME_ENGINE_LOCAL_MODE_MENTION: u32 = 11;
144pub const MSIME_ENGINE_LOCAL_MODE_URL: u32 = 12;
145pub const MSIME_ENGINE_LOCAL_MODE_CHAIZI: u32 = 13;
146pub const MSIME_ENGINE_LOCAL_MODE_SYMBOL: u32 = 14;
147
148// ---- 标志位 ----
149
150/// `msime_engine_key_char` 的 `flags`:这是单独按下的 Shift 加字母(大写字母开本地模式的入口)。
151pub const MSIME_ENGINE_KEY_SHIFT_ONLY: u32 = 1 << 0;
152
153/// `msime_engine_state::flags`:候选是上屏后的联想,只接受显式选择,空格、回车不上屏它们。
154pub const MSIME_ENGINE_STATE_PREDICTION: u32 = 1 << 0;
155/// `msime_engine_state::flags`:专用英文模式开着。
156pub const MSIME_ENGINE_STATE_DEDICATED_ENGLISH: u32 = 1 << 1;
157/// `msime_engine_state::flags`:方案可打开的候选列表(韩文汉字)正开着。
158pub const MSIME_ENGINE_STATE_CANDIDATE_LIST_OPEN: u32 = 1 << 2;
159/// `msime_engine_state::flags`:此刻的 `'` 是分隔符(单位与目标之间、`/fy` 的词之间),要按字符交给 `msime_engine_key_char`,不能当标点结束组字。
160pub const MSIME_ENGINE_STATE_TAKES_SEPARATOR: u32 = 1 << 3;
161
162/// `msime_engine_candidate::flags`:按模糊音读出的行。
163pub const MSIME_ENGINE_CANDIDATE_FUZZY: u32 = 1 << 0;
164/// `msime_engine_candidate::flags`:这一行回答的是整段输入,不是它的前缀或更长的补全。
165pub const MSIME_ENGINE_CANDIDATE_ANSWERS_KEY: u32 = 1 << 1;
166/// `msime_engine_candidate::flags`:整句联想解出的整句。
167pub const MSIME_ENGINE_CANDIDATE_SENTENCE: u32 = 1 << 2;
168
169/// `msime_engine_select_edge` 的 `edge`:上屏这一行的第一个汉字。
170pub const MSIME_ENGINE_EDGE_FIRST_HAN: u32 = 0;
171/// `msime_engine_select_edge` 的 `edge`:上屏这一行的最后一个汉字。
172pub const MSIME_ENGINE_EDGE_LAST_HAN: u32 = 1;
173
174/// `msime_engine_flush_learning` 的 `flags`:写完之后停掉后台写线程并等它结束。卸载库或退出进程前用;之后会话照常可用,下一次学习重新起线程。
175pub const MSIME_ENGINE_FLUSH_STOP_THREAD: u32 = 1 << 0;
176
177/// `msime_engine_user_dict_list` 的 `flags`:同时列出随包多字词被学习或编辑过的拼音权重。
178pub const MSIME_ENGINE_USER_DICT_INCLUDE_LEARNED: u32 = 1 << 0;
179
180/// `msime_engine_preload_model` 的 `kind`:`msime-japanese.dat`。
181pub const MSIME_ENGINE_MODEL_JAPANESE: u32 = 1;
182
183/// `msime_engine_set_caret` 的 `caret_byte` 取这个值(或任何负数)时光标回到末尾。
184pub const MSIME_ENGINE_CARET_END: i64 = -1;
185
186// ---- 会话选项编号(`msime_engine_set_int` / `msime_engine_set_string`) ----
187
188/// 整数:中文标点开关,0 或 1。
189pub const MSIME_ENGINE_OPTION_CHINESE_PUNCT: u32 = 1;
190/// 整数:成对标点开关,0 或 1。
191pub const MSIME_ENGINE_OPTION_PAIRED_PUNCT: u32 = 2;
192/// 整数:标点锁,0 跟随模式、1 强制中文、2 强制 ASCII。
193pub const MSIME_ENGINE_OPTION_PUNCT_LOCK: u32 = 3;
194/// 整数:专用英文模式,0 或 1;只在模式真的改变时丢弃组字。
195pub const MSIME_ENGINE_OPTION_DEDICATED_ENGLISH: u32 = 4;
196/// 整数:辅助码开关(全拼和双拼一起),0 或 1。
197pub const MSIME_ENGINE_OPTION_HELPCODE_ENABLED: u32 = 5;
198/// 字符串:辅助码表名,例如 `wubi86`;读不到表时 `MSIME_ENGINE_FAILED`。
199pub const MSIME_ENGINE_OPTION_HELPCODE_SCHEMA: u32 = 6;
200/// 整数:个人上下文学习(词序与搭配),0 或 1;关掉时也结束当前上下文。
201pub const MSIME_ENGINE_OPTION_PERSONAL_CONTEXT: u32 = 7;
202/// 整数:宿主的即时隐私门禁,0 时清掉上屏后联想、之后不再给出,选项 `next_word_prediction` 本身不变。
203pub const MSIME_ENGINE_OPTION_PREDICTION_ALLOWED: u32 = 8;
204/// 整数:宿主每页的候选数(1 到 255);决定全长组的同音词够多少行就不再并入更长的补全词。
205pub const MSIME_ENGINE_OPTION_FIRST_PAGE_ROWS: u32 = 9;
206/// 字符串:整句模型参照的已上屏文字(只看最后 64 个字),宿主在光标前文字变化时交来。
207pub const MSIME_ENGINE_OPTION_RESCORING_CONTEXT: u32 = 10;
208/// 整数,ABI 1.1 起:调频方式,`MSIME_ENGINE_FREQUENCY_*`,与选项 `frequency.mode` 相同。从下一次选择起按新方式学,已经学下的排序照旧生效,眼前的候选不重排。
209pub const MSIME_ENGINE_OPTION_FREQUENCY_MODE: u32 = 11;
210/// 整数,ABI 1.1 起:同一个词要被选中几次才挪位(1 到 10),与选项 `frequency.trigger_count` 相同。
211pub const MSIME_ENGINE_OPTION_FREQUENCY_TRIGGER_COUNT: u32 = 12;
212/// 整数,ABI 1.1 起:`MSIME_ENGINE_FREQUENCY_LINEAR` 每次前移几位(1 到 10),与选项 `frequency.linear_step` 相同。
213pub const MSIME_ENGINE_OPTION_FREQUENCY_LINEAR_STEP: u32 = 13;
214/// 整数,ABI 1.1 起:五笔拼音混输(码表没有时按全拼出字),0 或 1,与选项 `wubi.mixed_pinyin` 相同;五笔组字中切换时立即按新设置重查候选。
215pub const MSIME_ENGINE_OPTION_WUBI_MIXED_PINYIN: u32 = 14;
216
217// ---- 调频方式(`MSIME_ENGINE_OPTION_FREQUENCY_MODE` 的取值,ABI 1.1 起,冻结) ----
218
219/// 不调频:选词不改变以后的排序(缺省)。
220pub const MSIME_ENGINE_FREQUENCY_DISABLED: u32 = 0;
221/// 选中的词直接排到首位。
222pub const MSIME_ENGINE_FREQUENCY_PIN: u32 = 1;
223/// 选中的词挪到原位置的一半处:下标 n 挪到 n/2(下标从 0 数)。
224pub const MSIME_ENGINE_FREQUENCY_HALVE: u32 = 2;
225/// 选中的词前移 `linear_step` 位。
226pub const MSIME_ENGINE_FREQUENCY_LINEAR: u32 = 3;
227/// 选中的词前移一位;下标大于 4 的直接挪到下标 4(第 5 位)。
228pub const MSIME_ENGINE_FREQUENCY_PROMOTE: u32 = 4;