本小节介绍模块 API 提供的一些便捷函数。与前几小节描述的函数一样,它们实际上都是函数指针,需要通过 emacs_env 指针调用。Emacs 25 之后新增的函数会标注其首次可用的版本。
bool eq (emacs_env *env, emacs_value a, emacs_value b) ¶如果 a 和 b 表示的 Lisp 对象完全相同,该函数返回 true,否则返回 false。这与 Lisp 函数 eq 功能一致(see 相等性谓词),但无需对参数表示的对象进行实例化。
API 未提供其他相等性判断函数,因此你需要使用下文介绍的 intern 和 funcall 执行更复杂的相等性测试。
bool is_not_nil (emacs_env *env, emacs_value arg) ¶该函数测试 arg 表示的 Lisp 对象是否为非 nil,并相应返回 true 或 false。
注意,你也可以通过 intern 获取表示 nil 的 emacs_value,再使用上文介绍的 eq 进行相等性判断,实现等效的测试。但使用该函数更便捷。
emacs_value type_of (emacs_env *env, emacs_value arg) ¶该函数以符号值的形式返回 arg 的类型:字符串对应 string、整数对应 integer、进程对应 process 等。See 类型谓词。如果代码需要根据对象类型执行逻辑,可以使用 intern 和 eq 与已知的类型符号进行比较。
emacs_value intern (emacs_env *env, const char *name) ¶该函数返回一个已实例化的 Emacs 符号,其名称为 name(需为以空字符结尾的 ASCII 字符串)。如果符号不存在,会创建一个新符号。
结合下文介绍的 funcall,该函数提供了调用任意可被 Lisp 调用的 Emacs 函数的方法,前提是函数名为纯 ASCII 字符串。例如,以下代码通过调用功能更强大的 Emacs intern 函数(see 创建与编入符号),实例化名称为非 ASCII 字符串 name_str 的符号:
emacs_value fintern = env->intern (env, "intern"); emacs_value sym_name = env->make_string (env, name_str, strlen (name_str)); emacs_value symbol = env->funcall (env, fintern, 1, &sym_name);
emacs_value funcall (emacs_env *env, emacs_value func, ptrdiff_t nargs, emacs_value *args) ¶该函数调用指定的 func,并从 args 指向的数组中传递 nargs 个参数。参数 func 可以是函数符号(例如上文介绍的 intern 返回值)、make_function 返回的模块函数(see 编写模块函数)、C 语言编写的子例程等。如果 nargs 为 0,args 可以是 NULL 指针。
函数返回 func 的执行结果。
如果你的模块包含可能长时间运行的代码,建议在代码中定期检查用户是否希望退出,例如通过按下 C-g(see 退出)。以下函数从 Emacs 26.1 版本开始可用,用于实现该功能。
bool should_quit (emacs_env *env) ¶如果用户希望退出,该函数返回 true。此时建议模块函数中止所有正在进行的处理并尽快返回。大多数情况下,建议使用 process_input 替代。
除了检查用户是否希望退出,还需要处理输入事件时,使用以下函数,该函数从 Emacs 27.1 版本开始可用。
enum emacs_process_input_result process_input (emacs_env *env) ¶该函数处理待处理的输入事件。如果用户希望退出或处理信号时发生错误,返回 emacs_process_input_quit。此时建议模块函数中止所有正在进行的处理并尽快返回。如果模块代码可以继续运行,process_input 返回 emacs_process_input_continue。返回值为 emacs_process_input_continue 当且仅当 env 中无待处理的非本地退出。如果模块在调用 process_input 后继续执行,变量值、缓冲区内容等全局状态可能被任意修改。
int open_channel (emacs_env *env, emacs_value pipe_process) ¶该函数从 Emacs 28 版本开始可用,打开指向现有管道进程的通道。pipe_process 必须引用由 make-pipe-process 创建的现有管道进程。Pipe Processes。如果执行成功,返回值为一个新的文件描述符,可用于向管道写入数据。与其他所有模块函数不同,返回的文件描述符可以在任意线程中使用,即使没有活动的模块环境。你可以使用 write 函数向文件描述符写入数据,操作完成后使用 close 关闭文件描述符。(libc)Low-Level I/O。