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

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

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

Генерация заголовочных файлов

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

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

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

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

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

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

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

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

Интегрируйте сгенерированный модуль:

  • Инструмент создаст папку imported/plugin_from_another_language/ с файлами core.cs, enums.cs, aliases.cs и delegates.cs в указанной выходной директории.
  • Скопируйте сгенерированную папку в директорию вашего проекта.
  • Укажите плагин в dependencies своего манифеста, чтобы он загружался раньше вашего.

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

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

Скопируйте модуль в проект

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

cp -r ./output/imported/plugin_from_another_language ./MyPlugin/

Добавьте в .csproj

SDK-проекты компилируют все файлы .cs в папке проекта, поэтому скопированные файлы подхватятся сами. Если ваш проект перечисляет файлы явно, добавьте их в .csproj:

<ItemGroup>
    <Compile Include="plugin_from_another_language\**\*.cs" />
</ItemGroup>

Или добавьте каждый файл вручную:

<ItemGroup>
    <Compile Include="plugin_from_another_language\core.cs" />
    <Compile Include="plugin_from_another_language\enums.cs" />
    <Compile Include="plugin_from_another_language\aliases.cs" />
    <Compile Include="plugin_from_another_language\delegates.cs" />
</ItemGroup>

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

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

using plugin_from_another_language;

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

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

Пример сгенерированного заголовочного файла

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

imported/plugin_from_another_language/core.cs
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Plugify;

// Generated from plugin_from_another_language.pplugin (group: core)

namespace plugin_from_another_language {
#pragma warning disable CS0649

    internal static unsafe partial class plugin_from_another_language {

#region ParamCallback
        private static delegate*<int, float, double, Vector4, long[], Char8, string, Char16, short, void> _ParamCallback = &___ParamCallback;
        private static delegate* unmanaged[Cdecl]<int, float, double, Vector4*, Vector192*, Char8, String192*, Char16, short, void> __ParamCallback;
        private static void ___ParamCallback(int a, float b, double c, Vector4 d, long[] e, Char8 f, string g, Char16 h, short k)
        {
            var __e = NativeMethods.ConstructVectorInt64(e, e.Length);
            var __g = NativeMethods.ConstructString(g);
            try {
                __ParamCallback(a, b, c, &d, &__e, f, &__g, h, k);
            }
            finally {
                // Perform cleanup.
                NativeMethods.DestroyVectorInt64(&__e);
                NativeMethods.DestroyString(&__g);
            }
        }
#endregion ParamCallback

        internal static void ParamCallback(int a, float b, double c, Vector4 d, long[] e, Char8 f, string g, Char16 h, short k)
        {
            _ParamCallback(a, b, c, d, e, f, g, h, k);
        }
    }
}

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

  • ParamCallback: метод, который вы вызываете в своём коде на C#.
  • Обертка (___ParamCallback) преобразует строки и массивы в типы Plugify и очищает их после вызова.
  • Указатель __ParamCallback заполняет языковой модуль при загрузке вашего плагина. Если другой плагин тоже написан на C#, модуль направляет _ParamCallback прямо на его метод, без преобразования.

Пример: Использование сгенерированного заголовочного файла

Вот как вы можете использовать сгенерированный заголовочный файл в вашем плагине на C#:

plugin.cs
using System.Numerics;
using plugin_from_another_language;

public class MyPlugin {
    public void MyFunction() {
        // Вызов экспортированной функции из другого плагина
        plugin_from_another_language.plugin_from_another_language.ParamCallback(
            42,                // int a
            3.14f,             // float b
            2.718,             // double c
            new Vector4(1, 2, 3, 4), // Vector4 d
            new long[] { 100, 200 }, // long[] e
            'x',               // Char8 f
            "Hello, Plugify!", // string g
            '✓',               // Char16 h
            10                 // short k
        );
    }
}

Когда необходима генерация заголовочных файлов?

В C# сгенерированные привязки нужны для каждого импортируемого плагина, на каком бы языке он ни был написан. Без них компилятор не сможет ссылаться на экспортированные функции. Плагинам на динамически типизированных языках, таких как Python, этот шаг не нужен, поскольку привязка методов происходит во время выполнения.

Лучшие практики

  1. Используйте инструмент-генератор: Всегда используйте инструмент-генератор Plugify (онлайн или командной строки) для генерации заголовочных файлов для импортируемых функций.
  2. Подключайте сгенерированные файлы: Подключайте сгенерированные заголовочные файлы в исходные файлы вашего плагина для доступа к экспортированным функциям.
  3. Тестируйте тщательно: Тестируйте импортированные функции, чтобы убедиться, что они работают так, как ожидается.
  4. Документируйте зависимости: Четко документируйте плагины и функции, от которых зависит ваш плагин.

Заключение

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