2025-11-27 01:34:37 +07:00

47 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Plugins lesson 3.
| | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Умеет формировать API для подключения плагинов. <br> <br>Умеет создавать и собирать плагины в соответствии с заданным API. <br>(C) <br> <br>Умеет подключать и отключать плагины в рантайме. (загрузка библиотеки и ее выгрузка) | На примере торговых ботов для биржи создадим систему с возможностью подключения плагинов. Научимся формировать API для плагинов, собирать и подключать их в рантайме, а также управлять ими — включать и отключать по мере необходимости. <br> <br>Урок - практический. Студент после него сможет писать аналогичные решения, что мы и проверим в проекте. <br> <br>Торговый бот - контекст, в котором показываются примеры (не production bot) <br> <br>Придумать API |
## Start
В прошлых уроках мы узнали, что используя dlopen и dlsym можно динамически подгружать функции из отдельных файлов динамических библиотек. Это бывает полезно для уменьшения размера программы на диске и в оперативной памяти, а также выноса зависимостей в рациональные.
В этом уроке мы изучим взаимодействие с динамическими кодом более высокоуровневым способом: системой плагинов.
## Система плагинов
Система плагинов представляет собой подгружаемый функционал, взаимодействие с которым возможно через заранее определенный интерфейс. Как концепцию плагины можно представить так: определение интерфейса это прописывание трейта, а реализация трейта - уже сами плагины, но не вшитые в саму программу, а находящиеся в отдельном файле.
Давайте попробуем сделать систему плагинов для собственного торгового бота. Пускай интерфейсом будет одна функция trade, которая по переданому срезу u32 цен будет принимать решение: купить, продать или ничего не делать:
```rust
pub enum TradeAction {
Sell(u32),
Buy(u32),
None,
}
pub struct PluginInterface {
pub trade: extern "Rust" fn(prices: &[u32]) -> TradeAction,
}
```
Основная программа, после подгрузки плагина сможет по такому интерфейсу сможет воспользоваться плагином. Теперь, библиотеку с таким интерфейсом нужно как-нибудь подгружать. Это можно сделать используя dlopen и dlsym, но в данном примере для удобства воспользуемся библиотекой libloading.
```rust
pub struct Plugin {
plugin: Library,
}
impl Plugin {
pub fn new(filename: &str) -> Result<Self, libloading::Error> {
Ok(Plugin {
plugin: unsafe { libloading::Library::new(filename) }?,
})
}
pub fn interface(&self) -> Result<PluginInterface<'_>, libloading::Error> {
Ok(PluginInterface {
trade: unsafe { self.plugin.get("trade") }?,
})
}
}
```
Тут придется немного изменить интерфейс плагина, так как libloading добавляет лайфтаймы к функциям:
```rust
pub struct PluginInterface<'a> {
pub trade: Symbol<'a, extern "Rust" fn(prices: &[u32]) -> TradeAction>,
}
```