/* * Tencent is pleased to support the open source community by making ScriptX available. * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include "../../src/Reference.h" #include "../../src/Scope.h" #include "LuaEngine.h" #include "LuaHelper.h" namespace script::lua_backend { inline LuaEngine* currentEngine() { return &EngineScope::currentEngineCheckedAs(); } inline lua_State* currentLua() { return currentEngine()->lua_; } /** * run a balanced stack scope */ template inline void luaStackScope(lua_State* lua, Block&& block) { #ifndef NDEBUG auto top = lua_gettop(lua); block(); // assert the stack is balanced assert(top == lua_gettop(lua)); #else block(); #endif } inline void luaEnsureStack(lua_State* lua, int size) { if (!lua_checkstack(lua, size)) { throw Exception("stack overflow"); } } /** * BE VERY CAREFUL with lua_error, it used longjmp to unwind stack, which WON'T CALL c++ * DESTRUCTORS. */ inline void luaThrow(lua_State* lua, const char* message) { lua_pushstring(lua, message); lua_error(lua); } /** * BE VERY CAREFUL with lua_error, it used longjmp to unwind stack, which WON'T CALL c++ * DESTRUCTORS. */ inline void luaThrow(lua_State* lua, std::optional& message) { if (message.has_value()) { lua_pushstring(lua, message->c_str()); // destruct std::string by hand message.~optional(); lua_error(lua); } } inline void pushValue(lua_State* lua, const Local& local) { luaEnsureStack(lua, 1); auto val = LuaEngine::localRefIndex(local); if (val == 0) { lua_pushnil(lua); } else { lua_pushvalue(lua, val); } } template void pushValues(lua_State* lua, size_t count, It begin) { luaEnsureStack(lua, static_cast(count)); for (size_t i = 0; i < count; ++i) { auto val = LuaEngine::localRefIndex(*begin); if (val == 0) { lua_pushnil(lua); } else { lua_pushvalue(lua, val); } ++begin; } } inline void rethrowException(lua_State* lua) { Exception exp(LuaEngine::make>(lua_gettop(lua))); lua_pop(lua, 1); throw exp; // NOLINT } } // namespace script::lua_backend namespace script { struct lua_interop { /** * get lua_State* from LuaEngine */ static lua_State* getEngineLua(lua_backend::LuaEngine* engine) { return engine->lua_; } static lua_State* currentEngineLua() { return ::script::lua_backend::currentLua(); } /** * convert Local to a lua local reference * @return the index in stack */ template static int toLua(const Local& ref) { return lua_backend::LuaEngine::localRefIndex(ref); } /** * create Local from lua local reference * @param index the index in stack */ template static Local makeLocal(int index) { return lua_backend::LuaEngine::make>(index); } static Arguments makeArguments(lua_backend::LuaEngine* engine, int stackBase, size_t paramCount, bool isInstanceFunc) { return lua_backend::LuaEngine::makeArguments(engine, stackBase, paramCount, isInstanceFunc); } using ArgumentsData = lua_backend::ArgumentsData; static ArgumentsData extractArguments(const Arguments& args) { return args.callbackInfo_; } }; } // namespace script