Импорт функций

Узнайте, как импортировать функции из других плагинов, написанных на разных языках, и использовать их в своём плагине.

Чтобы использовать функции другого плагина в вашем плагине на Rust, необходимо сгенерировать привязки для конкретного языка. Эти привязки предоставляют обёртки, необходимые для вызова функций, экспортируемых другими плагинами. Это руководство объясняет, как сгенерировать такие привязки и как использовать их в вашем плагине на Rust.

Генерация привязок для Rust

Plugify предоставляет единый инструмент-генератор для автоматического создания кода на Rust для импорта функций из других плагинов. Эти привязки включают функции-обёртки, которые обрабатывают вызовы функций и передачу параметров.

Шаги для генерации привязок Rust

Использование онлайн-генератора:

Перейдите на инструмент plugify-gen, чтобы сгенерировать привязки через удобный веб-интерфейс. Просто загрузите файл манифеста вашего плагина (.pplugin) и выберите Rust в качестве целевого языка, чтобы получить соответствующий файл .rs.

Использование инструмента командной строки:

Вы также можете загрузить и использовать генератор локально из репозитория plugify-gen.

Пример использования:

plugify-gen -manifest ./plugins/plugin_from_another_language/plugin_from_another_language.pplugin -output ./output/ -lang rust

Интеграция сгенерированного модуля:

  • Инструмент создаст папку модуля (например, plugin_from_another_language/) в указанном выходном каталоге.
  • Скопируйте всю сгенерированную папку модуля в каталог src/ вашего проекта.
  • Объявите модуль в вашем src/lib.rs.

Интеграция в проект

После генерации модуля интегрируйте его в ваш проект на Rust:

Копирование модуля в проект

Скопируйте сгенерированную папку модуля в каталог src/ вашего проекта:

cp -r ./output/plugin_from_another_language ./my_plugin/src/

Объявление модуля

Объявите модуль в вашем src/lib.rs:

mod plugin_from_another_language;

Импорт в исходных файлах

Импортируйте и используйте сгенерированный модуль в ваших файлах на Rust:

use crate::plugin_from_another_language;
// Или импортируйте конкретные элементы в область видимости
use crate::plugin_from_another_language::*;

Использование сгенерированных функций-обёрток

Сгенерированный модуль содержит функции-обёртки, которые позволяют вызывать функции из другого плагина. Эти обёртки обрабатывают поиск адреса функции и передачу параметров.

Пример сгенерированных привязок

Вот пример сгенерированного файла привязок Rust для плагина с именем plugin_from_another_language:

plugin_from_another_language.rs
// Generated from plugin_from_another_language.pplugin by https://github.com/untrustedmodders/plugify-gen

use plugify::*;

pub mod plugin_from_another_language {
    pub fn ParamCallback(a: i32, b: f32, c: f64, d: &Vec4, e: &Arr<i64>, f: i8, g: &Str, h: u16, k: i16) {
        unsafe { __plugin_from_another_language_ParamCallback.expect("ParamCallback function was not found")(a, b, c, d, e, f, g, h, k) }
    }
    pub type _ParamCallback = unsafe extern "C" fn(i32, f32, f64, &Vec4, &Arr<i64>, i8, &Str, u16, i16);
    #[allow(dead_code, non_upper_case_globals)]
    #[unsafe(no_mangle)]
    pub static mut __plugin_from_another_language_ParamCallback: Option<_ParamCallback> = None;
}

Как это работает

  • Функция-обёртка (ParamCallback) получает адрес экспортированной функции через API Plugify.
  • Делегат __plugin_from_another_language_ParamCallback устанавливается языковым модулем во время загрузки плагина.
  • Функция-обёртка напрямую передаёт параметры в экспортированную функцию.

Пример: использование сгенерированных привязок

Вот как можно использовать сгенерированные привязки в вашем плагине на Rust:

src/lib.rs
mod plugin_from_another_language;

use plugify::*;
use plugin_from_another_language::*;

fn on_plugin_start() {
    // Вызов экспортированной функции из другого плагина
    let data = Arr::from(vec![100i64, 200i64]);
    let message = Str::from("Hello, Plugify!");
    let vec4 = Vec4::new(1.0, 2.0, 3.0, 4.0);

    plugin_from_another_language::ParamCallback(
        42,          // i32 a
        3.14,        // f32 b
        2.718,       // f64 c
        &vec4,       // &Vec4 d
        &data,       // &Arr<i64> e
        'x' as i8,   // i8 f
        &message,    // &Str g
        '✓' as u16,  // u16 h
        10           // i16 k
    );
}

register_plugin!(
    start: on_plugin_start
);

Работа с типами PlgTypes

Plugify использует специальные типы для межъязыковой совместимости:

Str

use plugify::Str;

// Создание из строкового литерала Rust
let msg = Str::from("Hello");

// Создание из String
let msg = Str::from(String::from("Hello"));

// Преобразование в &str
let s: &str = msg.as_str();

// Преобразование в String
let string: String = msg.to_string();

Arr<T>

use plugify::Arr;

// Создание из Vec
let numbers = Arr::from(vec![1, 2, 3, 4, 5]);

// Создание пустого массива
let mut data: Arr<i32> = Arr::new();
data.push(42);

// Доступ к элементам
let first = data[0];

// Итерация
for num in &numbers {
    println!("{}", num);
}

// Преобразование в Vec
let vec: Vec<i32> = numbers.into();

Var

use plugify::Var;

// Создание из разных типов
let var1 = Var::from(Any::Int32(42));
let var2 = Var::from(Any::Float(3.14));
let var3 = Var::from(Any::String("text"));

// Извлечение значения
match var1.get() {
    Any::Int32(num) => println!("Number: {}", num),
    _ => println!("NA"),
}

Когда необходима генерация привязок?

Генерация привязок необходима при импорте функций из плагинов, написанных на других языках. Без этих привязок вы не сможете безопасно вызывать экспортированные функции. Генератор обеспечивает типобезопасность и корректную совместимость ABI.

Рекомендации

  1. Используйте инструмент-генератор: Всегда используйте генератор Plugify (онлайн или командную строку) для создания привязок к импортируемым функциям.
  2. Подключайте сгенерированные модули: Размещайте сгенерированные файлы в каталоге модулей и подключайте их в своём плагине.
  3. Безопасно обрабатывайте ошибки: Проверяйте указатели на функции на null перед вызовом импортированных функций.
  4. Документируйте зависимости: Чётко документируйте плагины и функции, от которых зависит ваш плагин.
  5. Используйте типы PlgTypes: Всегда используйте Str, Arr<T> и Var для межъязыковой совместимости.
  6. Учитывайте владение: Будьте внимательны с заимствованными ссылками и владеющими значениями.

Заключение

Импорт функций из другого плагина в Rust выполняется просто, если вы используете генератор Plugify для создания необходимых привязок. Эти привязки предоставляют безопасные функции-обёртки, которые обрабатывают поиск адреса функции и передачу параметров, что упрощает интеграцию функциональности из других плагинов. Следуя шагам и рекомендациям, изложенным в этом руководстве, вы сможете создавать надёжные и совместимые плагины в экосистеме Plugify с гарантиями безопасности Rust.