Для того, чтобы сделать свой 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 по полочкам:
Для более подробного примера рекомендую ознакомиться с кодом недавно вышедшего MoonAdditions, в нём куча всего, так что примеров более, чем достаточно.
Возможно вам также понадобится документация по Sol2 - она здесь.
Небольшое дополнение: луа автоматически выгружает модули, которые больше не используются скриптами (только если использующий скрипт сам был выгружен), и если в вашем модуле нужно использовать какие-то хуки/патчи или что-либо, что требует работы без выгрузки длл, можно запретить его выгрузку с помощью следующего кода. Этот метод используется и в MoonAdditions.
Переименовать свой модуль можно просто изменив название самого проекта.
Download (Скачать)
Проект включает в себя враппер для 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);
Возможно вам также понадобится документация по 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 (Скачать)
Последнее редактирование: