16.11 Emacs 动态模块

Emacs 动态模块(dynamic Emacs module) 是一种共享库,可为 Emacs Lisp 程序提供额外功能,与使用 Emacs Lisp 编写的包类似。

用于加载 Emacs Lisp 包的函数同样可以加载动态模块。系统通过文件名扩展名(也称 “后缀(suffix)”)识别动态模块,该后缀与平台相关。

Variable: module-file-suffix

该变量保存模块文件的文件名扩展名,其值与系统相关。 在 POSIX 系统上为 .so,macOS 上为 .dylib,MS-Windows 上为 .dll

在 macOS 上,动态模块除了 .dylib 之外,也可以使用后缀 .so

每个动态模块都应导出一个名为 emacs_module_init 的 C 可调用函数,Emacs 会在通过 loadrequire 加载模块时调用它。 模块还应导出一个名为 plugin_is_GPL_compatible 的符号,表明其代码基于 GPL 或兼容协议发布; 如果程序尝试加载未导出该符号的模块,Emacs 会报错。

如果模块需要调用 Emacs 函数,应通过 Emacs 发行版中附带的头文件 emacs-module.h 所定义并说明的 API(应用程序编程接口)实现。 See Writing Dynamically-Loaded Modules 查看编写模块时使用该 API 的详细信息。

模块可以创建 user-ptr 类型的 Lisp 对象,用于存放指向模块所定义的 C 结构体的指针。 这便于保存模块创建的复杂数据结构,并将其传回给模块的函数使用。 user-ptr 对象还可以关联 终结函数(finalizer)——在对象被垃圾回收(GC)时执行的函数, 可用于释放底层数据结构占用的资源,如内存、打开的文件描述符等。See Conversion Between Lisp and Module Values

Function: user-ptrp object

如果参数是 user-ptr 对象,该函数返回 t

Function: module-load file

Emacs 使用这个底层原语从指定的 file 加载模块并完成必要的初始化。 该原语会检查模块是否导出了 plugin_is_GPL_compatible 符号,调用模块的 emacs_module_init 函数, 若该函数返回错误或初始化期间用户按下 C-g,则报错。 若初始化成功,module-load 返回 t。 注意:file 必须已经带有正确的扩展名,因为与 load 不同,该函数不会自动尝试已知后缀的文件。

load 不同,module-load 不会将模块记入 load-history,不打印任何信息,也不防止递归加载。 因此大多数用户应使用 loadload-fileload-libraryrequire,而非直接使用 module-load

Emacs 中的可加载模块需要在 configure 时使用 --with-modules 选项启用。


emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike