Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

解决lua调用c++自定义导出函数传递nil参数奔溃问题 #711

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions Plugins/UnLua/Source/UnLua/Public/UnLuaEx.inl
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ namespace UnLua
return TTuple<T...>(UnLua::Get(L, Offset + N, TType<T>())...);
}

/**
* Get arguments from Lua stack, avoid nullptr access crash but throw lua error
*/
template <typename... T, uint32... N>
FORCEINLINE_DEBUGGABLE TTuple<T...> GetArgsChecked(lua_State *L, TIndices<N...>, uint32 Offset = 0)
{
return TTuple<T...>(UnLua::GetChecked(L, Offset + N, TType<T>())...);
}

/**
* Generic closure to help invoke exported function
Expand Down Expand Up @@ -367,7 +375,7 @@ namespace UnLua
return 0;
}

TTuple<typename TArgTypeTraits<ArgType>::Type...> Args = GetArgs<typename TArgTypeTraits<ArgType>::Type...>(L, typename TOneBasedIndices<Expected>::Type(), 1);
TTuple<typename TArgTypeTraits<ArgType>::Type...> Args = GetArgsChecked<typename TArgTypeTraits<ArgType>::Type...>(L, typename TOneBasedIndices<Expected>::Type(), 1);
Construct(L, Args, typename TZeroBasedIndices<Expected>::Type());
return 1;
}
Expand Down Expand Up @@ -444,7 +452,7 @@ namespace UnLua
return 0;
}

TTuple<typename TArgTypeTraits<ArgType>::Type...> Args = GetArgs<typename TArgTypeTraits<ArgType>::Type...>(L, typename TOneBasedIndices<Expected>::Type());
TTuple<typename TArgTypeTraits<ArgType>::Type...> Args = GetArgsChecked<typename TArgTypeTraits<ArgType>::Type...>(L, typename TOneBasedIndices<Expected>::Type());
Construct(L, Args, typename TZeroBasedIndices<Expected>::Type());
return 1;
}
Expand Down Expand Up @@ -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<typename TArgTypeTraits<ArgType>::Type...> Args = GetArgs<typename TArgTypeTraits<ArgType>::Type...>(L, typename TOneBasedIndices<Expected>::Type());
TTuple<typename TArgTypeTraits<ArgType>::Type...> Args = GetArgsChecked<typename TArgTypeTraits<ArgType>::Type...>(L, typename TOneBasedIndices<Expected>::Type());
return TInvokingHelper<RetType>::Invoke(L, Func, Args, typename TZeroBasedIndices<Expected>::Type());
}

Expand Down Expand Up @@ -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<ClassType*, typename TArgTypeTraits<ArgType>::Type...> Args = GetArgs<ClassType*, typename TArgTypeTraits<ArgType>::Type...>(L, typename TOneBasedIndices<Expected>::Type());
TTuple<ClassType*, typename TArgTypeTraits<ArgType>::Type...> Args = GetArgsChecked<ClassType*, typename TArgTypeTraits<ArgType>::Type...>(L, typename TOneBasedIndices<Expected>::Type());
if (Args.template Get<0>() == nullptr)
{
UE_LOG(LogUnLua, Error, TEXT("Attempted to call %s::%s with nullptr of 'this'."), *ClassName, *Name);
Expand Down
78 changes: 69 additions & 9 deletions Plugins/UnLua/Source/UnLua/Public/UnLuaLegacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,12 +474,25 @@ namespace UnLua
/**
* Get value from the stack.
*/
template <typename T> T Get(lua_State* L, int32 Index, TType<T>);
template <typename T> auto Get(lua_State *L, int32 Index, TType<T>)
-> std::enable_if_t<!std::is_base_of<TTypeCheckable<T>, TType<T>>::value, T>;

template <typename T> T* Get(lua_State* L, int32 Index, TType<T*>);
template <typename T> auto Get(lua_State *L, int32 Index, TType<T>)
-> std::enable_if_t<std::is_base_of<TTypeCheckable<T>, TType<T>>::value, T>;

template <typename T> T& Get(lua_State* L, int32 Index, TType<T&>);
template <typename T> T* Get(lua_State *L, int32 Index, TType<T*>);

template <typename T> T& Get(lua_State *L, int32 Index, TType<T&>);

template <typename T> auto GetChecked(lua_State *L, int32 Index, TType<T>)
-> std::enable_if_t<!std::is_base_of<TTypeCheckable<T>, TType<T>>::value, T>;

template <typename T> auto GetChecked(lua_State *L, int32 Index, TType<T>)
-> std::enable_if_t<std::is_base_of<TTypeCheckable<T>, TType<T>>::value, T>;

template <typename T> T* GetChecked(lua_State *L, int32 Index, TType<T*>);

template <typename T> T& GetChecked(lua_State *L, int32 Index, TType<T&>);
template <typename T> TSubclassOf<T> Get(lua_State* L, int32 Index, TType<TSubclassOf<T>>);
template <typename T> TSubclassOf<T>* Get(lua_State* L, int32 Index, TType<TSubclassOf<T>*>);
template <typename T> TSubclassOf<T>& Get(lua_State* L, int32 Index, TType<TSubclassOf<T>&>);
Expand Down Expand Up @@ -1007,9 +1020,11 @@ namespace UnLua
return TPointerHelper<typename TRemoveReference<T>::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<typename TDecay<T>::Type>::GetName());
return *V;
}
};
Expand All @@ -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);
}
};


Expand Down Expand Up @@ -1068,24 +1088,64 @@ namespace UnLua
* Get value from the stack.
*/
template <typename T>
FORCEINLINE T Get(lua_State* L, int32 Index, TType<T>)
FORCEINLINE auto Get(lua_State *L, int32 Index, TType<T>)
-> std::enable_if_t<!std::is_base_of<TTypeCheckable<T>, TType<T>>::value, T>
{
return TGenericTypeHelper<T>::Get(L, Index);
}

template <typename T>
FORCEINLINE auto Get(lua_State *L, int32 Index, TType<T> Ty)
-> std::enable_if_t<std::is_base_of<TTypeCheckable<T>, TType<T>>::value, T>
{
return TGenericTypeHelper<T>::Get(L, Index, Ty.bIfNeedCheck);
}

template <typename T>
FORCEINLINE T* Get(lua_State* L, int32 Index, TType<T*>)
FORCEINLINE T* Get(lua_State *L, int32 Index, TType<T*>)
{
return TPointerHelper<T>::Get(L, Index);
}

template <typename T>
FORCEINLINE T& Get(lua_State* L, int32 Index, TType<T&>)
FORCEINLINE T& Get(lua_State *L, int32 Index, TType<T&>)
{
T* V = TPointerHelper<T>::Get(L, Index);
T *V = TPointerHelper<T>::Get(L, Index);
return *V;
}

template <typename T>
FORCEINLINE auto GetChecked(lua_State *L, int32 Index, TType<T> Ty)
-> std::enable_if_t<!std::is_base_of<TTypeCheckable<T>, TType<T>>::value, T>
{
// NOT Checkable type && in check context, using custom UnLua::Get
return Get(L, Index, Ty);
}

template <typename T>
FORCEINLINE auto GetChecked(lua_State *L, int32 Index, TType<T> Ty)
-> std::enable_if_t<std::is_base_of<TTypeCheckable<T>, TType<T>>::value, T>
{
// Checkable type && in check context, using custom UnLua::Get or TGenericTypeHelper<T>::Get
Ty.EnableCheck();
return Get(L, Index, Ty);
}

template <typename T>
FORCEINLINE T* GetChecked(lua_State *L, int32 Index, TType<T*> Ty)
{
return Get(L, Index, Ty);
}

template <typename T>
FORCEINLINE T& GetChecked(lua_State *L, int32 Index, TType<T&>)
{
T *V = TPointerHelper<T>::Get(L, Index);
if ( UNLIKELY(!V) )
luaL_typeerror(L, lua_absindex(L, Index), TType<typename TDecay<T>::Type>::GetName());
return *V;
}

template <typename T>
FORCEINLINE TSubclassOf<T> Get(lua_State* L, int32 Index, TType<TSubclassOf<T>>)
{
Expand Down
30 changes: 30 additions & 0 deletions Plugins/UnLua/Source/UnLua/Public/UnLuaTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,3 +343,33 @@ DEFINE_TYPE(FText)
DEFINE_SMART_POINTER(TSharedPtr)
DEFINE_SMART_POINTER(TSharedRef)
DEFINE_SMART_POINTER(TWeakPtr)

/**
* Define container names
*/
template<typename ElementType, typename Allocator>
struct UnLua::TType<TArray<ElementType, Allocator>, false>
{
static const char * GetName()
{
return "TArray<>";
}
};

template<typename KeyType, typename ValueType, typename SetAllocator, typename KeyFunc>
struct UnLua::TType<TMap<KeyType, ValueType, SetAllocator, KeyFunc>, false>
{
static const char * GetName()
{
return "TMap<>";
}
};

template<typename InElementType, typename KeyFunc, typename Allocator>
struct UnLua::TType<TSet<InElementType, KeyFunc, Allocator>, false>
{
static const char * GetName()
{
return "TSet<>";
}
};