Исходник Гайд Создание DLL-модуля под MoonLoader при помощи Sol2

FYP

Известный
Автор темы
Администратор
1,763
5,899
Для того, чтобы сделать свой DLL-модуль для lua по этому шаблону потребуется Microsoft Visual Studio 2015 или выше и немножко знаний C++, всё остальное уже включено в проект.
Проект включает в себя враппер для Lua API - Sol2, с парой мелких изменений под LuaJIT и сами библиотеки LuaJIT. Тонкости настройки здесь рассматриваться не будут, он уже настроен и готов к компиляции, а желающие сами могут посмотреть какая конфигурация у проекта.
Sol2 в этом шаблоне является основой взаимодействия между C++ и Lua, рекомендую в проекте использовать только его и не прибегать к стандартному API Lua без крайней необходимости.

Исходный код включает следующие файлы:
pch.cpp - основной файл для создания предкомпилированного заголовка, вносить изменения и вообще обращать на него внимание не нужно
pch.h - сам заголовочный файл предкомпилированного заголовка, сюда можно добавить всякие стандартные инклуды (windows.h, vector, algorithm и т.п.)
lua_module.h - несколько вспомогательных макросов, чтоб скрыть некрасивый код экспортируемой функции регистрации модуля. Редактировать тоже не нужно
main.cpp - основной исходник

main.cpp по полочкам:
C++:
#include "pch.h"
#include "lua_module.h"

// эта функция будет вызвана каждый раз, когда какой-то из луа скриптов впервые за сеанс своей работы загружает модуль с помощью стандартной функции require
// функция имеет один аргумент - sol::this_state ts, он хранит lua_state вызвавшего её потока, через него и происходит взаимодействие с луа-машиной
sol::table open(sol::this_state ts)
{
    // т.к. sol::this_state это по сути простой указатель, а для взаимодействия нужен интерфейс, создаём sol::state_view lua из него
    // sol::state_view это класс с большим количеством функций для управления lua_state
    sol::state_view lua{ts};
 
    // создаём пустую таблицу для наполнения её своими функциями, переменными и всяким таким
    // внимание, спойлер: в конце она будет возвращена функцией open
    sol::table module = lua.create_table();
 
    // добавляем элемент с названием "VERSION" и значением 1337, это типо версия нашего модуля
    // этим же способом данные редактируются, если они уже существуют, т.е. как и в луа
    module["VERSION"] = 1337;
 
    // а тут добавляем свою функцию под названием "test", в этом примере она принимает лямбду - это почти то же самое, что и обычная функция, но обычные функции тоже можно использовать
    // так: module.set_function("test", &my_function); // my_function тут это типо ваша функция
    module.set_function("test", [](sol::this_state ts) {
        // опять же, создаём state_view из this_state, потому что хотим вызвать скриптовую функцию print
        sol::state_view lua{ts};
        // вызываем её, передав строку тупа ни о чем
        lua["print"]("testing testing, 1 2 3");
    });

    // возвращаем нашу таблицу
    // а скрипт, вызвавший эту функцию кодом local my_module = require 'my_module' получит её и сможет получить значение элемента "VERSION" и вызывать нашу функцию "test"
    // вот так:
    // print(my_module.VERSION)
    // my_module.test()
    return module;
}

// собственно, один из тех самых макросов, скрывающих уродливый код
// добавляет экспортируемую функцию с названием luaopen_%your_module_name% и пихает внутрь неё вызов функции open
SOL_MODULE_ENTRYPOINT(open);
Для более подробного примера рекомендую ознакомиться с кодом недавно вышедшего MoonAdditions, в нём куча всего, так что примеров более, чем достаточно.
Возможно вам также понадобится документация по Sol2 - она здесь.

Небольшое дополнение: луа автоматически выгружает модули, которые больше не используются скриптами (только если использующий скрипт сам был выгружен), и если в вашем модуле нужно использовать какие-то хуки/патчи или что-либо, что требует работы без выгрузки длл, можно запретить его выгрузку с помощью следующего кода. Этот метод используется и в MoonAdditions.
C++:
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
    {
        // pin DLL to prevent unloading
        HMODULE module;
        GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, reinterpret_cast<LPCWSTR>(&DllMain), &module);
    }
    return TRUE;
}

Переименовать свой модуль можно просто изменив название самого проекта.

Download (Скачать)
 
Последнее редактирование:

_DK

Новичок
7
20
Для тех, кто хотел бы создать свой модуль для MoonLoader, используя plugin-sdk:

В Мастер настройки проекта plugin-sdk добавлена возможность настроить модуль для MoonLoader.

MPm5GA9.png
 

#Northn

Pears Project — уже запущен!
Всефорумный модератор
2,650
2,535
Выпускаю проект, готовый для сборки на Visual Studio 2017 для Windows 7, 8.1 и 10.
Обновил до sol3 3.2.2 от 2020 года
Добавил режим дебага и он работает, если что-то из настроек не так — сообщите, я починю.
 

Вложения

  • moonloader_module_sdk.zip
    176.8 KB · Просмотры: 168

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,762
2,587
Пример проекта под CMake, с использованием FetchContent для подтягивания sol'а, в данный момент используется версия 3.3.1
1723072365304.png
 
  • Нравится
Реакции: kyrtion