本文档适用于:
- 想要理解插件工作方式的开发者
- 希望移植到其他语言以便其他语言可以开发插件的开发者
如果您是开发插件的开发者, 请参阅插件开发文档
本文档所提及的插件
均为可以被AtriBot直接加载的原生动态库插件,
其余的一切不符合上述要求的插件
均不在本文范畴内
插件均使用C abi
保证插件的ABI层面接口稳定(如果您不知道何为C abi请移步Bing)
所有的插件
都应暴露两个函数:
atri_manager_init
和on_init
插件位于加载目录下时会先通过系统加载动态库, 然后搜寻上述的两个函数。
本函数为插件管理器的初始化函数,
插件加载会最先调用本函数,
函数接收一个结构体AtriManager
(结构体定义位于ffi.rs)
函数定义如下
#[no_mangle]
unsafe extern "C" fn atri_manager_init(manager: AtriManager) {
// 在此进行初始化操作
}
void atri_manager_init(AtriManager manager) {
// 在此进行初始化操作
}
本函数为插件实例初始化函数,
调用返回结构体PluginInstance
作为插件的实例
(结构体定义位于plugin.rs)
函数定义如下
#[no_mangle]
extern "C" fn on_init() -> PluginInstance {
// 初始化插件实例
}
PluginInstance on_init() {
// 初始化插件实例
}
此函数调用后, 插件加载基本完毕
在上述加载过程执行完毕返回的插件实例内包含了插件的虚表,
插件启用前会调用插件的new
函数指针得到插件实例指针
若should_drop
为true
,
则每次启用都会通过new
构造一个实例
(插件实例结构在每次调用new
时都不应变更)
然后会使用该指针调用enable
函数用于启用插件
注意: 重复启用一个插件是无效果的
禁用插件会调用disable
函数,
若should_drop
为true
,
则会在disable
执行完毕后调用drop
函数销毁插件实例
注意: 重复禁用一个插件是无效果的
卸载插件会先禁用此插件,
然后调用他的drop
函数销毁插件实例,
最后会释放动态库文件完成整个插件的生命周期
插件与主程序可以通过加载阶段得到的AtriManager
进行交互,
内部的函数指针get_fun
传入一个uint16
得到另一个函数指针,
所有的函数定义位于plugin/ffi/mod.rs
推荐在加载阶段将所需的全部函数保存为全局变量
传入未定义的sig
会得到一个调用就会panic的函数
插件的new
和drop
规则是迎合Rust设计得到的,
在其他语言可以适当调整其功能
原设计模式适用于: Rust, C/C++
其他模式,如: 单例插件的new
返回固定值,
固定should_drop
标志为false,
drop
函数作为插件卸载行为函数。
此模式可能适用于: Go和Kotlin/Native