diff --git a/Plugins/UnLua/Source/UnLua/Public/UnLuaEx.inl b/Plugins/UnLua/Source/UnLua/Public/UnLuaEx.inl index 1dc4e269..4fa14610 100644 --- a/Plugins/UnLua/Source/UnLua/Public/UnLuaEx.inl +++ b/Plugins/UnLua/Source/UnLua/Public/UnLuaEx.inl @@ -250,6 +250,14 @@ namespace UnLua return TTuple(UnLua::Get(L, Offset + N, TType())...); } + /** + * Get arguments from Lua stack, avoid nullptr access crash but throw lua error + */ + template + FORCEINLINE_DEBUGGABLE TTuple GetArgsChecked(lua_State *L, TIndices, uint32 Offset = 0) + { + return TTuple(UnLua::GetChecked(L, Offset + N, TType())...); + } /** * Generic closure to help invoke exported function @@ -367,7 +375,7 @@ namespace UnLua return 0; } - TTuple::Type...> Args = GetArgs::Type...>(L, typename TOneBasedIndices::Type(), 1); + TTuple::Type...> Args = GetArgsChecked::Type...>(L, typename TOneBasedIndices::Type(), 1); Construct(L, Args, typename TZeroBasedIndices::Type()); return 1; } @@ -444,7 +452,7 @@ namespace UnLua return 0; } - TTuple::Type...> Args = GetArgs::Type...>(L, typename TOneBasedIndices::Type()); + TTuple::Type...> Args = GetArgsChecked::Type...>(L, typename TOneBasedIndices::Type()); Construct(L, Args, typename TZeroBasedIndices::Type()); return 1; } @@ -527,7 +535,7 @@ namespace UnLua UE_LOG(LogUnLua, Warning, TEXT("Attempted to call %s with invalid arguments. %d expected but got %d."), *Name, Expected, Actual); return 0; } - TTuple::Type...> Args = GetArgs::Type...>(L, typename TOneBasedIndices::Type()); + TTuple::Type...> Args = GetArgsChecked::Type...>(L, typename TOneBasedIndices::Type()); return TInvokingHelper::Invoke(L, Func, Args, typename TZeroBasedIndices::Type()); } @@ -579,7 +587,7 @@ namespace UnLua UE_LOG(LogUnLua, Warning, TEXT("Attempted to call %s::%s with invalid arguments. %d expected but got %d."), *ClassName, *Name, Expected, Actual); return 0; } - TTuple::Type...> Args = GetArgs::Type...>(L, typename TOneBasedIndices::Type()); + TTuple::Type...> Args = GetArgsChecked::Type...>(L, typename TOneBasedIndices::Type()); if (Args.template Get<0>() == nullptr) { UE_LOG(LogUnLua, Error, TEXT("Attempted to call %s::%s with nullptr of 'this'."), *ClassName, *Name); diff --git a/Plugins/UnLua/Source/UnLua/Public/UnLuaLegacy.h b/Plugins/UnLua/Source/UnLua/Public/UnLuaLegacy.h index 418b7095..c1ca0e31 100644 --- a/Plugins/UnLua/Source/UnLua/Public/UnLuaLegacy.h +++ b/Plugins/UnLua/Source/UnLua/Public/UnLuaLegacy.h @@ -474,12 +474,25 @@ namespace UnLua /** * Get value from the stack. */ - template T Get(lua_State* L, int32 Index, TType); + template auto Get(lua_State *L, int32 Index, TType) + -> std::enable_if_t, TType>::value, T>; - template T* Get(lua_State* L, int32 Index, TType); + template auto Get(lua_State *L, int32 Index, TType) + -> std::enable_if_t, TType>::value, T>; - template T& Get(lua_State* L, int32 Index, TType); + template T* Get(lua_State *L, int32 Index, TType); + template T& Get(lua_State *L, int32 Index, TType); + + template auto GetChecked(lua_State *L, int32 Index, TType) + -> std::enable_if_t, TType>::value, T>; + + template auto GetChecked(lua_State *L, int32 Index, TType) + -> std::enable_if_t, TType>::value, T>; + + template T* GetChecked(lua_State *L, int32 Index, TType); + + template T& GetChecked(lua_State *L, int32 Index, TType); template TSubclassOf Get(lua_State* L, int32 Index, TType>); template TSubclassOf* Get(lua_State* L, int32 Index, TType*>); template TSubclassOf& Get(lua_State* L, int32 Index, TType&>); @@ -1007,9 +1020,11 @@ namespace UnLua return TPointerHelper::Type>::Push(L, &V); } - static T Get(lua_State* L, int32 Index) + static T Get(lua_State *L, int32 Index, bool bIfNeedCheck = false) { - T* V = (T*)UnLua::GetPointer(L, Index); + T *V = (T*)UnLua::GetPointer(L, Index); + if ( UNLIKELY(!V) && bIfNeedCheck ) + luaL_typeerror(L, lua_absindex(L, Index), TType::Type>::GetName()); return *V; } }; @@ -1027,6 +1042,11 @@ namespace UnLua { return (T)lua_tointeger(L, Index); } + + static T Get(lua_State *L, int32 Index, bool bIfNeedCheck = false) + { + return (T)lua_tointeger(L, Index); + } }; @@ -1068,24 +1088,64 @@ namespace UnLua * Get value from the stack. */ template - FORCEINLINE T Get(lua_State* L, int32 Index, TType) + FORCEINLINE auto Get(lua_State *L, int32 Index, TType) + -> std::enable_if_t, TType>::value, T> { return TGenericTypeHelper::Get(L, Index); } + template + FORCEINLINE auto Get(lua_State *L, int32 Index, TType Ty) + -> std::enable_if_t, TType>::value, T> + { + return TGenericTypeHelper::Get(L, Index, Ty.bIfNeedCheck); + } + template - FORCEINLINE T* Get(lua_State* L, int32 Index, TType) + FORCEINLINE T* Get(lua_State *L, int32 Index, TType) { return TPointerHelper::Get(L, Index); } template - FORCEINLINE T& Get(lua_State* L, int32 Index, TType) + FORCEINLINE T& Get(lua_State *L, int32 Index, TType) { - T* V = TPointerHelper::Get(L, Index); + T *V = TPointerHelper::Get(L, Index); return *V; } + template + FORCEINLINE auto GetChecked(lua_State *L, int32 Index, TType Ty) + -> std::enable_if_t, TType>::value, T> + { + // NOT Checkable type && in check context, using custom UnLua::Get + return Get(L, Index, Ty); + } + + template + FORCEINLINE auto GetChecked(lua_State *L, int32 Index, TType Ty) + -> std::enable_if_t, TType>::value, T> + { + // Checkable type && in check context, using custom UnLua::Get or TGenericTypeHelper::Get + Ty.EnableCheck(); + return Get(L, Index, Ty); + } + + template + FORCEINLINE T* GetChecked(lua_State *L, int32 Index, TType Ty) + { + return Get(L, Index, Ty); + } + + template + FORCEINLINE T& GetChecked(lua_State *L, int32 Index, TType) + { + T *V = TPointerHelper::Get(L, Index); + if ( UNLIKELY(!V) ) + luaL_typeerror(L, lua_absindex(L, Index), TType::Type>::GetName()); + return *V; + } + template FORCEINLINE TSubclassOf Get(lua_State* L, int32 Index, TType>) { diff --git a/Plugins/UnLua/Source/UnLua/Public/UnLuaTemplate.h b/Plugins/UnLua/Source/UnLua/Public/UnLuaTemplate.h index 38b51ec9..17c15614 100644 --- a/Plugins/UnLua/Source/UnLua/Public/UnLuaTemplate.h +++ b/Plugins/UnLua/Source/UnLua/Public/UnLuaTemplate.h @@ -343,3 +343,33 @@ DEFINE_TYPE(FText) DEFINE_SMART_POINTER(TSharedPtr) DEFINE_SMART_POINTER(TSharedRef) DEFINE_SMART_POINTER(TWeakPtr) + +/** + * Define container names + */ +template +struct UnLua::TType, false> +{ + static const char * GetName() + { + return "TArray<>"; + } +}; + +template +struct UnLua::TType, false> +{ + static const char * GetName() + { + return "TMap<>"; + } +}; + +template +struct UnLua::TType, false> +{ + static const char * GetName() + { + return "TSet<>"; + } +}; \ No newline at end of file