// - LuaState::doStringOrFile ----------------------------------------------- LuaValueList LuaState::doStringOrFile (bool isString, const std::string& str) { const int stackSizeAtBeginning = lua_gettop (state_); if (isString) { Impl::ThrowOnLuaError (state_, luaL_loadbuffer (state_, str.c_str(), str.length(), "line")); } else { Impl::ThrowOnLuaError (state_, luaL_loadfile (state_, str.c_str())); } Impl::ThrowOnLuaError (state_, lua_pcall (state_, 0, LUA_MULTRET, 0)); const int numResults = lua_gettop (state_) - stackSizeAtBeginning; LuaValueList results; for (int i = numResults; i > 0; --i) results.push_back (ToLuaValue (state_, -i)); lua_pop (state_, numResults); return results; }
static int tolua_lua_cocos2dx_userext_LuaValueList_pushString00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( !tolua_isusertype(tolua_S,1,"LuaValueList",0,&tolua_err) || !tolua_isstring(tolua_S,2,0,&tolua_err) || !tolua_isnoobj(tolua_S,3,&tolua_err) ) goto tolua_lerror; else #endif { LuaValueList* self = (LuaValueList*) tolua_tousertype(tolua_S,1,0); const char* val = ((const char*) tolua_tostring(tolua_S,2,0)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'pushString'", NULL); #endif { self->pushString(val); } } return 0; #ifndef TOLUA_RELEASE tolua_lerror: tolua_error(tolua_S,"#ferror in function 'pushString'.",&tolua_err); return 0; #endif }
static int tolua_lua_cocos2dx_userext_LuaValueList_clear00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( !tolua_isusertype(tolua_S,1,"LuaValueList",0,&tolua_err) || !tolua_isnoobj(tolua_S,2,&tolua_err) ) goto tolua_lerror; else #endif { LuaValueList* self = (LuaValueList*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'clear'", NULL); #endif { self->clear(); } } return 0; #ifndef TOLUA_RELEASE tolua_lerror: tolua_error(tolua_S,"#ferror in function 'clear'.",&tolua_err); return 0; #endif }
LuaValueList LuaVariable::operator() (const LuaValue& param1, const LuaValue& param2) { LuaValueList params; params.push_back (param1); params.push_back (param2); return (*this)(params); }
TEST_F(LuaFunctionTest, SetCFunction) { { ScopedLuaStackTest stackTest(L); LuaFunction func = LuaFunction::createFromCFunction(L, testCFunction); LuaValueList retVals = func(); ASSERT_EQ(1, (int)retVals.size()); ASSERT_EQ(ValueType::NUMBER, retVals[0].getValueType()); ASSERT_DOUBLE_EQ(42.0, retVals[0].getValue<double>()); } }
TEST_F(LuaFunctionTest, Call) { { ScopedLuaStackTest stackTest(L); // Test execution with failure LuaFunction function = LuaFunction::createFromCode(L, "invalid()"); ASSERT_THROW(function.call(), luacpp::LuaException); ASSERT_THROW(function(), luacpp::LuaException); } { ScopedLuaStackTest stackTest(L); // Test execution without failure LuaFunction function = LuaFunction::createFromCode(L, "local a = 1"); ASSERT_NO_THROW(function.call()); ASSERT_NO_THROW(function()); } { ScopedLuaStackTest stackTest(L); // Test execution without failure LuaFunction function = LuaFunction::createFromCode(L, "return 'abc', 5"); LuaValueList returnValues = function(); ASSERT_EQ(luacpp::ValueType::STRING, returnValues[0].getValueType()); ASSERT_EQ(luacpp::ValueType::NUMBER, returnValues[1].getValueType()); ASSERT_STREQ("abc", returnValues[0].getValue<std::string>().c_str()); ASSERT_EQ(5, returnValues[1].getValue<int>()); } { ScopedLuaStackTest stackTest(L); lua_getglobal(L, "type"); LuaFunction func; ASSERT_TRUE(convert::popValue(L, func)); LuaValue arg = LuaValue::createValue(L, "testString"); LuaValueList returnVals = func({ arg }); ASSERT_EQ(1, (int)returnVals.size()); ASSERT_EQ(ValueType::STRING, returnVals[0].getValueType()); ASSERT_STREQ("string", returnVals[0].getValue<std::string>().c_str()); } }
LuaValue::LuaValue (const LuaValueList& v) { if (v.size() >= 1) *this = v[0]; else *this = Nil; }
TEST_F(LuaFunctionTest, SetEnvironment) { { ScopedLuaStackTest stackTest(L); // Setup environment table LuaTable envionment = LuaTable::create(L); envionment.addValue("key", "Test"); LuaFunction func = LuaFunction::createFromCode(L, "return key"); func.setEnvironment(envionment); LuaValueList returnVals = func(); ASSERT_EQ(1, (int)returnVals.size()); ASSERT_EQ(ValueType::STRING, returnVals[0].getValueType()); ASSERT_STREQ("Test", returnVals[0].getValue<std::string>().c_str()); } }
LuaFunction LuaFunction::createFromCFunction(lua_State* L, lua_CFunction function, const LuaValueList& upvalues) { LuaFunction func; for (auto& val : upvalues) { val.pushValue(); } lua_pushcclosure(L, function, (int) upvalues.size()); func.setReference(UniqueLuaReference::create(L)); lua_pop(L, 1); return func; }
LuaValueList LuaFunction::call(const LuaValueList& args) { int err_idx = 0; int stackTop; if (_errorFunction) { // push the error function _errorFunction->pushValue(); err_idx = lua_gettop(_luaState); stackTop = err_idx; } else { stackTop = lua_gettop(_luaState); } // Push the function onto the stack this->pushValue(); // Push the arguments onto the stack for (LuaValueList::const_iterator iter = args.begin(); iter != args.end(); ++iter) { iter->pushValue(); } // actually call the function now! int err = lua_pcall(_luaState, (int) args.size(), LUA_MULTRET, err_idx); if (!err) { int numReturn = lua_gettop(_luaState) - stackTop; LuaValueList values; values.reserve(numReturn); LuaValue val; for (int i = 0; i < numReturn; ++i) { if (convert::popValue(_luaState, val)) { // Add values at the begin as the last return value is on top // of the stack. values.insert(values.begin(), val); } } if (err_idx != 0) { // Remove the error function lua_pop(_luaState, 1); } return values; } else { // Make sure that there is exactly one parameter left on the stack // If the error function didn't return anything then this will push nil // If it pushed more than one value then this will discard all of them except the last one lua_settop(_luaState, stackTop + 1); std::string err_msg; if (!lua_isstring(_luaState, -1)) { err_msg = "Invalid lua value on stack!"; lua_pop(_luaState, 1); // Remove the value on the stack } else { err_msg = convert::popValue<std::string>(_luaState); } // Throw exception with generated message LuaException exception(err_msg); if (err_idx != 0) { // Pop the error function lua_pop(_luaState, 1); } throw exception; } }
LuaValueList LuaFunction::call(const LuaValueList& args) { int err_idx = 0; int stackTop; if (errorFunction) { // push the error function errorFunction->pushValue(); err_idx = lua_gettop(luaState); stackTop = err_idx; } else { stackTop = lua_gettop(luaState); } // Push the function onto the stack this->pushValue(); // Push the arguments onto the stack for (LuaValueList::const_iterator iter = args.begin(); iter != args.end(); ++iter) { iter->pushValue(); } // actually call the function now! int err = lua_pcall(luaState, args.size(), LUA_MULTRET, err_idx); if (!err) { int numReturn = lua_gettop(luaState) - stackTop; LuaValueList values; values.reserve(numReturn); LuaValue val; for (int i = 0; i < numReturn; ++i) { auto top = lua_gettop(luaState); if (convert::popValue(luaState, val)) { top = lua_gettop(luaState); // Add values at the begin as the last return value is on top // of the stack. values.insert(values.begin(), val); } } if (err_idx != 0) { // Remove the error function lua_remove(luaState, err_idx); } return values; } else { // Throw exception with generated message LuaException exception(convert::popValue<std::string>(luaState)); if (err_idx != 0) { // Pop the error function lua_pop(luaState, 1); } throw exception; } }