// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "lua_global.h" #include #include #include #include #include #include // this needs to be included after sol/sol.hpp! #include "luaqttypes.h" #include #include namespace Lua { class LuaEnginePrivate; class LuaPluginSpec; namespace Internal { class LuaPlugin; } struct CoroutineState { bool isMainThread; }; struct ScriptPluginSpec { QString name; Utils::FilePath appDataPath; std::unique_ptr connectionGuard; }; class LUA_EXPORT LuaEngine final : public QObject { friend class Internal::LuaPlugin; protected: LuaEngine(); public: using PackageProvider = std::function; ~LuaEngine(); static LuaEngine &instance(); Utils::expected_str loadPlugin(const Utils::FilePath &path); Utils::expected_str prepareSetup( sol::state_view &lua, const LuaPluginSpec &pluginSpec, sol::optional hookTable); static void registerProvider(const QString &packageName, const PackageProvider &provider); static void autoRegister(const std::function ®isterFunction); static void registerHook(QString name, const std::function &hookProvider); static Utils::expected_str connectHooks(sol::state_view lua, const sol::table &hookTable); static bool isCoroutine(lua_State *state); static sol::table toTable(const sol::state_view &lua, const QJsonValue &v); static QJsonValue toJson(const sol::table &t); template static void checkKey(const sol::table &table, const QString &key) { if (table[key].template is()) return; if (!table[key].valid()) throw sol::error("Expected " + key.toStdString() + " to be defined"); throw sol::error( "Expected " + key.toStdString() + " to be of type " + sol::detail::demangle()); } static QStringList variadicToStringList(const sol::variadic_args &vargs); template static Utils::expected_str safe_call(const sol::protected_function &function, Args &&...args) { sol::protected_function_result result = function(std::forward(args)...); if (!result.valid()) { sol::error err = result; return Utils::make_unexpected(QString::fromLocal8Bit(err.what())); } try { return result.get(); } catch (std::runtime_error &e) { return Utils::make_unexpected(QString::fromLocal8Bit(e.what())); } } template static Utils::expected_str void_safe_call( const sol::protected_function &function, Args &&...args) { sol::protected_function_result result = function(std::forward(args)...); if (!result.valid()) { sol::error err = result; return Utils::make_unexpected(QString::fromLocal8Bit(err.what())); } return {}; } // Runs the given script in a new Lua state. The returned Object manages the lifetime of the state. std::unique_ptr runScript(const QString &script, const QString &name); protected: Utils::expected_str connectHooks( sol::state_view lua, const sol::table &table, const QString &path); private: std::unique_ptr d; }; } // namespace Lua