Skip to content
This repository has been archived by the owner on Oct 21, 2023. It is now read-only.

Latest commit

 

History

History
108 lines (83 loc) · 3.07 KB

Plugin.md

File metadata and controls

108 lines (83 loc) · 3.07 KB

插件的加载方式及接口描述

本文档适用于:

  • 想要理解插件工作方式的开发者
  • 希望移植到其他语言以便其他语言可以开发插件的开发者

如果您是开发插件的开发者, 请参阅插件开发文档

本文档所提及的插件均为可以被AtriBot直接加载的原生动态库插件, 其余的一切不符合上述要求的插件均不在本文范畴内

接口稳定性

插件均使用C abi保证插件的ABI层面接口稳定(如果您不知道何为C abi请移步Bing)

加载

所有的插件都应暴露两个函数: atri_manager_initon_init

插件位于加载目录下时会先通过系统加载动态库, 然后搜寻上述的两个函数。

atri_manager_init

本函数为插件管理器的初始化函数, 插件加载会最先调用本函数, 函数接收一个结构体AtriManager (结构体定义位于ffi.rs)

函数定义如下

Rust:

#[no_mangle]
unsafe extern "C" fn atri_manager_init(manager: AtriManager) {
    // 在此进行初始化操作
}

C:

void atri_manager_init(AtriManager manager) {
    // 在此进行初始化操作
}

on_init

本函数为插件实例初始化函数, 调用返回结构体PluginInstance作为插件的实例 (结构体定义位于plugin.rs)

函数定义如下

Rust:

#[no_mangle]
extern "C" fn on_init() -> PluginInstance {
    // 初始化插件实例
}

C:

PluginInstance on_init() {
    // 初始化插件实例
}

此函数调用后, 插件加载基本完毕

启用

在上述加载过程执行完毕返回的插件实例内包含了插件的虚表, 插件启用前会调用插件的new函数指针得到插件实例指针 若should_droptrue, 则每次启用都会通过new构造一个实例 (插件实例结构在每次调用new时都不应变更)

然后会使用该指针调用enable函数用于启用插件

注意: 重复启用一个插件是无效果的

禁用

禁用插件会调用disable函数, 若should_droptrue, 则会在disable执行完毕后调用drop函数销毁插件实例

注意: 重复禁用一个插件是无效果的

卸载

卸载插件会先禁用此插件, 然后调用他的drop函数销毁插件实例, 最后会释放动态库文件完成整个插件的生命周期

交互

插件与主程序可以通过加载阶段得到的AtriManager进行交互, 内部的函数指针get_fun传入一个uint16得到另一个函数指针, 所有的函数定义位于plugin/ffi/mod.rs

推荐在加载阶段将所需的全部函数保存为全局变量

传入未定义的sig会得到一个调用就会panic的函数

其他

插件的newdrop规则是迎合Rust设计得到的, 在其他语言可以适当调整其功能

原设计模式适用于: Rust, C/C++

其他模式,如: 单例插件的new返回固定值, 固定should_drop标志为false, drop函数作为插件卸载行为函数。

此模式可能适用于: Go和Kotlin/Native