UE4 引擎剖析 - UnLua插件

UE4 引擎剖析 - UnLua插件

https://zhuanlan.zhihu.com/p/79050796

 

一、UnLua模塊的初始化:
class FUnLuaModule : public IModuleInterface
{
public:
virtual void StartupModule() override
{
// 創建Lua環境
FLuaContext::Create();
GLuaCxt->RegisterDelegates();
}

virtual void ShutdownModule() override
{
}
};

二、UnLua環境的創建
FLuaContext *GLuaCxt = nullptr;

// 創建全局的Lua環境對象
1. FLuaContext* FLuaContext::Create()
{
if (!GLuaCxt)
{
static FLuaContext Context;
GLuaCxt = &Context;
}
return GLuaCxt;
}

// 添加引擎的代理函數
2. void FLuaContext::RegisterDelegates()
{
/**
* 在引擎初始代理完成之前 FCoreDelegates::OnFEngineLoopInitComplete.Broadcast(),
* GEngine->Init(...) 執行之後調用 FLuaContext::OnPostEngineInit 。
*/
FCoreDelegates::OnPostEngineInit.AddRaw(GLuaCxt, &FLuaContext::OnPostEngineInit);

}

// 引擎初始化代理函數,開啓Lua環境
3. void FLuaContext::OnPostEngineInit()
{
#if AUTO_UNLUA_STARTUP
if (!GIsEditor)
{
// 開啓Lua環境
SetEnable(true);
}
#endif
}

// 創建lua_State、然後初始化
4. void FLuaContext::SetEnable(bool InEnable)
{
if (InEnable)
{
// 創建Lua狀態 lua_State
CreateState();
}

bEnable = InEnable;
if (bEnable)
{
// 初始化
Initialize();
}
}

5. 創建 lua_State
void FLuaContext::CreateState()
{
if (IsRunningCommandlet())
{
return;
}

if (!L)
{
L = lua_newstate(FLuaContext::LuaAllocator, nullptr); // create main Lua thread
}
}
// 初始化
void FLuaContext::Initialize()
{
if (!bEnable || bInitialized)
{
return;
}

FCollisionHelper::Initialize(); // initialize collision helper stuff

CreateState(); // create Lua main thread

// 初始化
if (L)
{
if (!bAddUObjectNotify)
{
GUObjectArray.AddUObjectCreateListener(GLuaCxt); // add listener for creating UObject
GUObjectArray.AddUObjectDeleteListener(GLuaCxt); // add listener for deleting UObject
bAddUObjectNotify = true;
}

bInitialized = true;

FUnLuaDelegates::OnLuaContextInitialized.Broadcast();
}
}

三、綁定Lua模塊到UObject
1. void FLuaContext::NotifyUObjectCreated(const UObjectBase *InObject, int32 Index)
{
UObjectBaseUtility *Object = (UObjectBaseUtility*)InObject;
TryToBindLua(Object); // try to bind a Lua module for the object
}

2. bool FLuaContext::TryToBindLua(UObjectBaseUtility *Object)
{
static UClass *InterfaceClass = UUnLuaInterface::StaticClass();
if (!Object->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) // filter out CDO and ArchetypeObjects
{
if (Class->ImplementsInterface(InterfaceClass)) // static binding
{
UFunction *Func = Class->FindFunctionByName(FName("GetModuleName")); // find UFunction 'GetModuleName'. hard coded!!!
if (Func)
{
if (Func->GetNativeFunc() && IsInGameThread())
{
FString ModuleName;
UObject *DefaultObject = Class->GetDefaultObject(); // get CDO
DefaultObject->UObject::ProcessEvent(Func, &ModuleName); // force to invoke UObject::ProcessEvent(...)
UClass *OuterClass = Func->GetOuterUClass(); // get UFunction's outer class
Class = OuterClass == InterfaceClass ? Class : OuterClass; // select the target UClass to bind Lua module
if (ModuleName.Len() < 1)
{
ModuleName = Class->GetName();
}

//////////////////////////////////////////////////////
// 調用管理器來綁定Lua模塊到UObject
return Manager->Bind(Object, Class, *ModuleName, GLuaDynamicBinding.InitializerTableRef); // bind!!!
}
}
}
}
return false;
}

3. bool UUnLuaManager::Bind(UObjectBaseUtility *Object, UClass *Class, const TCHAR *InModuleName, int32 InitializerTableRef)
{
// 第一步: 註冊UObject的Class到lua_State
if (!RegisterClass(L, Object->GetClass())) // register class first
{
return false;
}

FString *ModuleNamePtr = ModuleNames.Find(Class);
if (!ModuleNamePtr)
{
// 第二步: 加載Lua模塊
UnLua::FLuaRetValues RetValues = UnLua::Call(L, "require", TCHAR_TO_ANSI(InModuleName)); // require Lua module
bSuccess = RetValues.IsValid();
if (bSuccess)
{
// 第三步: 綁定
bSuccess = BindInternal(Object, Class, InModuleName, true); // bind!!!
}
}

return bSuccess;
}

四、綁定的具體過程:
// 1. 註冊反射信息
FClassDesc* RegisterClass(lua_State *L, UStruct *Struct, UStruct *SuperStruct)
{
if (!Struct)
{
UNLUA_LOGERROR(L, LogUnLua, Warning, TEXT("%s, Invalid UStruct!"), ANSI_TO_TCHAR(__FUNCTION__));
return nullptr;
}

TArray<FClassDesc*> Chain;
FClassDesc *ClassDesc = nullptr;
if (SuperStruct)
{
// 利用UObject的UClass反射註冊FClassDesc
ClassDesc = GReflectionRegistry.RegisterClass(Struct);
Chain.Add(ClassDesc);
// 利用UObject的UClass反射註冊FClassDesc
GReflectionRegistry.RegisterClass(SuperStruct, &Chain);
}
else
{
// 利用UObject的UClass反射註冊FClassDesc
ClassDesc = GReflectionRegistry.RegisterClass(Struct, &Chain);
}

// 註冊
if (!RegisterClassInternal(L, ClassDesc, Chain))
{
UE_LOG(LogUnLua, Warning, TEXT("%s: Failed to register UStruct!"), ANSI_TO_TCHAR(__FUNCTION__));
}
return ClassDesc;
}

// 利用UObject的UClass反射註冊FClassDesc
FClassDesc* FReflectionRegistry::RegisterClass(UStruct *InStruct, TArray<FClassDesc*> *OutChain)
{
if (!InStruct)
{
return nullptr;
}

FClassDesc::EType Type = FClassDesc::GetType(InStruct);
if (Type == FClassDesc::EType::UNKNOWN)
{
return nullptr;
}

FClassDesc **ClassDescPtr = Struct2Classes.Find(InStruct);
if (ClassDescPtr) // already registered ?
{
GetClassChain(*ClassDescPtr, OutChain);
return *ClassDescPtr;
}

FString ClassName = FString::Printf(TEXT("%s%s"), InStruct->GetPrefixCPP(), *InStruct->GetName());
FClassDesc *ClassDesc = RegisterClassInternal(ClassName, InStruct, Type);
GetClassChain(ClassDesc, OutChain);
return ClassDesc;
}

FClassDesc* FReflectionRegistry::RegisterClassInternal(const FString &ClassName, UStruct *Struct, FClassDesc::EType Type)
{
check(Struct && Type != FClassDesc::EType::UNKNOWN);
FClassDesc *ClassDesc = new FClassDesc(Struct, ClassName, Type);
Name2Classes.Add(FName(*ClassName), ClassDesc);
Struct2Classes.Add(Struct, ClassDesc);
if (!ClassDesc->IsNative())
{
NonNativeStruct2Classes.Add(Struct, ClassDesc);
}

FClassDesc *CurrentClass = ClassDesc;
TArray<FString> NameChain;
TArray<UStruct*> StructChain;
ClassDesc->GetInheritanceChain(NameChain, StructChain);
for (int32 i = 0; i < NameChain.Num(); ++i)
{
FClassDesc **Class = Struct2Classes.Find(StructChain[i]);
if (!Class)
{
CurrentClass->Parent = new FClassDesc(StructChain[i], NameChain[i], Type);
Name2Classes.Add(*NameChain[i], CurrentClass->Parent);
Struct2Classes.Add(StructChain[i], CurrentClass->Parent);
if (!CurrentClass->Parent->IsNative())
{
NonNativeStruct2Classes.Add(StructChain[i], CurrentClass->Parent);
}
}
else
{
CurrentClass->Parent = *Class;
break;
}
CurrentClass = CurrentClass->Parent;
}

return ClassDesc;
}

void FReflectionRegistry::GetClassChain(FClassDesc *ClassDesc, TArray<FClassDesc*> *OutChain)
{
if (OutChain)
{
while (ClassDesc)
{
OutChain->Add(ClassDesc);
ClassDesc = ClassDesc->Parent;
}
}
}

// 將收集到的ClassDesc信息註冊到lua_State
static bool RegisterClassInternal(lua_State *L, const FClassDesc *ClassDesc, TArray<FClassDesc*> &Chain)
{
if (ClassDesc)
{
FScopedSafeClass SafeClasses(Chain);

const FString &Name = ClassDesc->GetName();

int32 Type = luaL_getmetatable(L, TCHAR_TO_ANSI(*Name));
bool bSuccess = Type == LUA_TTABLE;
lua_pop(L, 1);
if (bSuccess)
{
UE_LOG(LogUnLua, Verbose, TEXT("Class %s is already registered!"), *Name);
return true;
}

TArray<UnLua::IExportedClass*> ExportedClasses;
UnLua::IExportedClass *ExportedClass = GLuaCxt->FindExportedReflectedClass(Chain.Last()->GetFName()); // find statically exported stuff...
if (ExportedClass)
{
ExportedClasses.Add(ExportedClass);
}
RegisterClassCore(L, Chain.Last(), nullptr, ExportedClasses.GetData(), ExportedClasses.Num());

for (int32 i = Chain.Num() - 2; i > -1; --i)
{
ExportedClass = GLuaCxt->FindExportedReflectedClass(Chain[i]->GetFName()); // find statically exported stuff...
if (ExportedClass)
{
ExportedClasses.Add(ExportedClass);
}
RegisterClassCore(L, Chain[i], Chain[i + 1], ExportedClasses.GetData(), ExportedClasses.Num());
}

return true;
}
return false;
}

static bool RegisterClassCore(lua_State *L, FClassDesc *InClass, const FClassDesc *InSuperClass, UnLua::IExportedClass **ExportedClasses, int32 NumExportedClasses)
{
check(InClass);
const TCHAR *InClassName = *InClass->GetName();
TStringConversion<TStringConvert<TCHAR, ANSICHAR>> ClassName(InClassName);

int32 Type = luaL_getmetatable(L, ClassName.Get());
if (Type == LUA_TTABLE)
{
UE_LOG(LogUnLua, Verbose, TEXT("%s: Class %s is already registered!"), ANSI_TO_TCHAR(__FUNCTION__), InClassName);
lua_pop(L, 1);
return true;
}

InClass->AddRef();

lua_pop(L, 1);
luaL_newmetatable(L, ClassName.Get()); // 1, will be used as meta table later (lua_setmetatable)

const TCHAR *InSuperClassName = nullptr;
if (InSuperClass)
{
InSuperClassName = *InSuperClass->GetName();
lua_pushstring(L, "ParentClass"); // 2
Type = luaL_getmetatable(L, TCHAR_TO_ANSI(InSuperClassName));
if (Type != LUA_TTABLE)
{
UNLUA_LOGERROR(L, LogUnLua, Warning, TEXT("%s, Invalid super class %s!"), ANSI_TO_TCHAR(__FUNCTION__), InSuperClassName);
}
lua_rawset(L, -3);
}

lua_pushstring(L, "__index"); // 2
lua_pushcfunction(L, Class_Index); // 3
lua_rawset(L, -3);

lua_pushstring(L, "__newindex"); // 2
lua_pushcfunction(L, Class_NewIndex); // 3
lua_rawset(L, -3);

UScriptStruct *ScriptStruct = InClass->AsScriptStruct();
if (ScriptStruct)
{
lua_pushlightuserdata(L, InClass); // FClassDesc

lua_pushstring(L, "Copy"); // Key
lua_pushvalue(L, -2); // FClassDesc
lua_pushcclosure(L, ScriptStruct_Copy, 1); // closure
lua_rawset(L, -4);

lua_pushstring(L, "__eq"); // Key
lua_pushvalue(L, -2); // FClassDesc
lua_pushcclosure(L, ScriptStruct_Compare, 1); // closure
lua_rawset(L, -4);

if (!(ScriptStruct->StructFlags & (STRUCT_IsPlainOldData | STRUCT_NoDestructor)))
{
lua_pushstring(L, "__gc"); // Key
lua_pushvalue(L, -2); // FClassDesc
lua_pushcclosure(L, ScriptStruct_Delete, 1); // closure
lua_rawset(L, -4);
}

lua_pushstring(L, "__call"); // Key
lua_pushvalue(L, -2); // FClassDesc
lua_pushcclosure(L, ScriptStruct_New, 1); // closure
lua_rawset(L, -4);

lua_pop(L, 1);
}
else
{
UClass *Class = InClass->AsClass();
if (Class != UObject::StaticClass() && Class != UClass::StaticClass())
{
lua_pushstring(L, "ClassDesc"); // Key
lua_pushlightuserdata(L, InClass); // FClassDesc
lua_rawset(L, -3);

lua_pushstring(L, "StaticClass"); // Key
lua_pushlightuserdata(L, InClass); // FClassDesc
lua_pushcclosure(L, Class_StaticClass, 1); // closure
lua_rawset(L, -3);

lua_pushstring(L, "Cast"); // Key
lua_pushcfunction(L, Class_Cast); // C function
lua_rawset(L, -3);

lua_pushstring(L, "__eq"); // Key
lua_pushcfunction(L, UObject_Identical); // C function
lua_rawset(L, -3);

lua_pushstring(L, "__gc"); // Key
lua_pushcfunction(L, UObject_Delete); // C function
lua_rawset(L, -3);
}
}

lua_pushvalue(L, -1); // set metatable to self
lua_setmetatable(L, -2);

if (ExportedClasses)
{
for (int32 i = 0; i < NumExportedClasses; ++i)
{
ExportedClasses[i]->Register(L);
}
}

SetTableForClass(L, ClassName.Get());

if (!InClass->IsNative())
{
GLuaCxt->AddLibraryName(InClassName);
}

UE_LOG(LogUnLua, Verbose, TEXT("Succeed to register class %s, super class is %s!"), InClassName, InSuperClassName ? InSuperClassName : TEXT("NULL"));

return true;
}


// 2. 加載Lua模塊
// UnLua::Call(L, "require", TCHAR_TO_ANSI(InModuleName)); // require Lua module

template <typename... T>
FORCEINLINE_DEBUGGABLE FLuaRetValues Call(lua_State *L, const char *FuncName, T&&... Args)
{
if (!L || !FuncName)
{
return FLuaRetValues(INDEX_NONE);
}

lua_pushcfunction(L, ReportLuaCallError);

lua_getglobal(L, FuncName);
if (lua_isfunction(L, -1) == false)
{
UE_LOG(LogUnLua, Warning, TEXT("Global function %s doesn't exist!"), ANSI_TO_TCHAR(FuncName));
lua_pop(L, 2);
return FLuaRetValues(INDEX_NONE);
}

return CallFunctionInternal(L, Forward<T>(Args)...);
}

template <typename... T>
FORCEINLINE_DEBUGGABLE FLuaRetValues CallFunctionInternal(lua_State *L, T&&... Args)
{
// make sure the function is on the top of the stack, and the message handler is below the function
int32 MessageHandlerIdx = lua_gettop(L) - 1;
check(MessageHandlerIdx > 0);
int32 NumArgs = PushArgs<false>(L, Forward<T>(Args)...);
int32 Code = lua_pcall(L, NumArgs, LUA_MULTRET, MessageHandlerIdx);
int32 TopIdx = lua_gettop(L);
if (Code == LUA_OK)
{
int32 NumResults = TopIdx - MessageHandlerIdx;
lua_remove(L, MessageHandlerIdx);
FLuaRetValues Result(NumResults);
return Result; // MoveTemp(Result);
}
lua_pop(L, TopIdx - MessageHandlerIdx + 1);
return FLuaRetValues(INDEX_NONE);
}


// 3. 真正綁定的地方
bool UUnLuaManager::BindInternal(UObjectBaseUtility *Object, UClass *Class, const FString &InModuleName, bool bNewCreated)
{
lua_State *L = *GLuaCxt;
TStringConversion<TStringConvert<TCHAR, ANSICHAR>> ModuleName(*InModuleName);

if (!bNewCreated)
{
if (!BindSurvivalObject(L, Object, Class, ModuleName.Get())) // try to bind Lua module for survival UObject again...
{
return false;
}

FString *ModuleNamePtr = ModuleNames.Find(Class);
if (ModuleNamePtr)
{
return true;
}
}

ModuleNames.Add(Class, InModuleName);
Classes.Add(InModuleName, Class);

// 1. 獲取Lua模塊裏面定義的所有函數
TSet<FName> &LuaFunctions = ModuleFunctions.Add(InModuleName);
GetFunctionList(L, ModuleName.Get(), LuaFunctions); // get all functions defined in the Lua module

// 2. 獲取所有可以重載的函數
TMap<FName, UFunction*> &UEFunctions = OverridableFunctions.Add(Class);
GetOverridableFunctions(Class, UEFunctions); // get all overridable UFunctions

// 3. 重載所有可以重載的函數
ENetMode NetMode = CheckObjectNetMode(Object, Class, bNewCreated);
OverrideFunctions(LuaFunctions, UEFunctions, Class, bNewCreated, NetMode); // try to override UFunctions

return ConditionalUpdateClass(Class, LuaFunctions, UEFunctions);
}

// 獲取Lua模塊裏面定義的所有函數
bool GetFunctionList(lua_State *L, const char *InModuleName, TSet<FName> &FunctionNames)
{
int32 Type = GetLoadedModule(L, InModuleName);
if (Type == LUA_TNIL)
{
return false;
}

int32 N = 1;
bool bNext = false;
do
{
bNext = TraverseTable(L, -1, &FunctionNames, GetFunctionName) > INDEX_NONE;
if (bNext)
{
lua_pushstring(L, "Super");
lua_rawget(L, -2);
++N;
bNext = lua_istable(L, -1);
}
} while (bNext);
lua_pop(L, N);
return true;
}

int32 GetLoadedModule(lua_State *L, const char *ModuleName)
{
if (!ModuleName)
{
UE_LOG(LogUnLua, Warning, TEXT("%s, Invalid module name!"), ANSI_TO_TCHAR(__FUNCTION__));
return LUA_TNIL;
}

lua_getglobal(L, "package");
lua_getfield(L, -1, "loaded");
int32 Type = lua_getfield(L, -1, ModuleName);
lua_remove(L, -2);
lua_remove(L, -2);
return Type;
}

int32 TraverseTable(lua_State *L, int32 Index, void *Userdata, bool(*TraverseWorker)(lua_State*, void*))
{
if (Index < 0 && Index > LUA_REGISTRYINDEX)
{
int32 Top = lua_gettop(L);
Index = Top + Index + 1;
}
int32 Type = lua_type(L, Index);
if (Type == LUA_TTABLE)
{
if (!lua_checkstack(L, 2))
{
return INDEX_NONE;
}

int32 NumElements = 0;
lua_pushnil(L);
while (lua_next(L, Index) != 0)
{
if (TraverseWorker)
{
bool b = TraverseWorker(L, Userdata);
if (b)
{
++NumElements;
}
}
lua_pop(L, 1);
}
return NumElements;
}
return INDEX_NONE;
}

static bool GetFunctionName(lua_State *L, void *Userdata)
{
int32 ValueType = lua_type(L, -1);
if (ValueType == LUA_TFUNCTION)
{
TSet<FName> *FunctionNames = (TSet<FName>*)Userdata;
#if SUPPORTS_RPC_CALL
FString FuncName(lua_tostring(L, -2));
if (FuncName.EndsWith(TEXT("_RPC")))
{
FuncName = FuncName.Left(FuncName.Len() - 4);
}
FunctionNames->Add(FName(*FuncName));
#else
FunctionNames->Add(FName(lua_tostring(L, -2)));
#endif
}
return true;
}

// 獲取所有可以重載的函數
void GetOverridableFunctions(UClass *Class, TMap<FName, UFunction*> &Functions)
{
if (!Class)
{
return;
}

// all 'BlueprintEvent'
for (TFieldIterator<UFunction> It(Class, EFieldIteratorFlags::IncludeSuper, EFieldIteratorFlags::ExcludeDeprecated, EFieldIteratorFlags::IncludeInterfaces); It; ++It)
{
UFunction *Function = *It;
if (Function->HasAnyFunctionFlags(FUNC_BlueprintEvent))
{
FName FuncName = Function->GetFName();
UFunction **FuncPtr = Functions.Find(FuncName);
if (!FuncPtr)
{
Functions.Add(FuncName, Function);
}
}
}

// all 'RepNotifyFunc'
for (int32 i = 0; i < Class->ClassReps.Num(); ++i)
{
UProperty *Property = Class->ClassReps[i].Property;
if (Property->HasAnyPropertyFlags(CPF_RepNotify))
{
UFunction *Function = Class->FindFunctionByName(Property->RepNotifyFunc);
if (Function)
{
UFunction **FuncPtr = Functions.Find(Property->RepNotifyFunc);
if (!FuncPtr)
{
Functions.Add(Property->RepNotifyFunc, Function);
}
}
}
}
}

// 重載所有可以重載的函數
void UUnLuaManager::OverrideFunctions(const TSet<FName> &LuaFunctions, TMap<FName, UFunction*> &UEFunctions, UClass *OuterClass, bool bCheckFuncNetMode, ENetMode NetMode)
{
for (const FName &LuaFuncName : LuaFunctions)
{
UFunction **Func = UEFunctions.Find(LuaFuncName);
if (Func)
{
UFunction *Function = *Func;
#if SUPPORTS_RPC_CALL
if (bCheckFuncNetMode)
{
if ((Function->HasAnyFunctionFlags(FUNC_NetClient) && (NetMode == NM_DedicatedServer || NetMode == NM_ListenServer || NetMode == NM_MAX)) ||
(Function->HasAnyFunctionFlags(FUNC_NetServer) && (NetMode == NM_Client || NetMode == NM_MAX)))
{
continue;
}
}
#endif
OverrideFunction(Function, OuterClass, LuaFuncName);
}
}
}

void UUnLuaManager::OverrideFunction(UFunction *TemplateFunction, UClass *OuterClass, FName NewFuncName)
{
if (TemplateFunction->GetOuter() != OuterClass)
{
AddFunction(TemplateFunction, OuterClass, NewFuncName); // add a duplicated UFunction to child UClass
}
else
{
ReplaceFunction(TemplateFunction, OuterClass); // replace thunk function and insert opcodes
}
}

// 添加
void UUnLuaManager::AddFunction(UFunction *TemplateFunction, UClass *OuterClass, FName NewFuncName)
{
UFunction *Func = OuterClass->FindFunctionByName(NewFuncName, EIncludeSuperFlag::ExcludeSuper);
if (!Func)
{
// 複製一個函數
UFunction *NewFunc = DuplicateUFunction(TemplateFunction, OuterClass, NewFuncName); // duplicate a UFunction
if (!NewFunc->HasAnyFunctionFlags(FUNC_Native) && NewFunc->Script.Num() > 0)
{
NewFunc->Script.Empty(3); // insert opcodes for non-native UFunction only
}
OverrideUFunction(NewFunc, (FNativeFuncPtr)&FLuaInvoker::execCallLua, GReflectionRegistry.RegisterFunction(NewFunc)); // replace thunk function and insert opcodes
TArray<UFunction*> &DuplicatedFuncs = DuplicatedFunctions.FindOrAdd(OuterClass);
DuplicatedFuncs.AddUnique(NewFunc);
#if ENABLE_CALL_OVERRIDDEN_FUNCTION
GReflectionRegistry.AddOverriddenFunction(NewFunc, TemplateFunction);
#endif
}
}

// 複製一個函數
UFunction* DuplicateUFunction(UFunction *TemplateFunction, UClass *OuterClass, FName NewFuncName)
{
// (int32)offsetof(UProperty, RepNotifyFunc) - sizeof(int32); // offset for Offset_Internal... todo: use UProperty::Link()
static int32 Offset = offsetof(FFakeProperty, Offset_Internal);

UFunction *NewFunc = DuplicateObject(TemplateFunction, OuterClass, NewFuncName);
NewFunc->PropertiesSize = TemplateFunction->PropertiesSize;
NewFunc->MinAlignment = TemplateFunction->MinAlignment;
int32 NumParams = NewFunc->NumParms;
if (NumParams > 0)
{
NewFunc->PropertyLink = Cast<UProperty>(NewFunc->Children);
UProperty *SrcProperty = Cast<UProperty>(TemplateFunction->Children);
UProperty *DestProperty = NewFunc->PropertyLink;
while (true)
{
check(SrcProperty && DestProperty);
DestProperty->ArrayDim = SrcProperty->ArrayDim;
DestProperty->ElementSize = SrcProperty->ElementSize;
DestProperty->PropertyFlags = SrcProperty->PropertyFlags;
DestProperty->RepIndex = SrcProperty->RepIndex;
*((int32*)((uint8*)DestProperty + Offset)) = *((int32*)((uint8*)SrcProperty + Offset)); // set Offset_Internal ...
if (--NumParams < 1)
{
break;
}
DestProperty->PropertyLinkNext = Cast<UProperty>(DestProperty->Next);
DestProperty = DestProperty->PropertyLinkNext;
SrcProperty = SrcProperty->PropertyLinkNext;
}
}
OuterClass->AddFunctionToFunctionMap(NewFunc, NewFuncName);
//GReflectionRegistry.RegisterFunction(NewFunc);
if (GUObjectArray.DisregardForGCEnabled() || GUObjectClusters.GetNumAllocatedClusters())
{
NewFunc->AddToRoot();
}
return NewFunc;
}

// 替換
void UUnLuaManager::ReplaceFunction(UFunction *TemplateFunction, UClass *OuterClass)
{
FNativeFuncPtr *NativePtr = CachedNatives.Find(TemplateFunction);
if (!NativePtr)
{
#if ENABLE_CALL_OVERRIDDEN_FUNCTION
FName NewFuncName(*FString::Printf(TEXT("%s%s"), *TemplateFunction->GetName(), TEXT("Copy")));
UFunction *NewFunc = DuplicateUFunction(TemplateFunction, OuterClass, NewFuncName);
GReflectionRegistry.AddOverriddenFunction(TemplateFunction, NewFunc);
#endif
CachedNatives.Add(TemplateFunction, TemplateFunction->GetNativeFunc());
if (!TemplateFunction->HasAnyFunctionFlags(FUNC_Native) && TemplateFunction->Script.Num() > 0)
{
CachedScripts.Add(TemplateFunction, TemplateFunction->Script);
TemplateFunction->Script.Empty(3);
}
OverrideUFunction(TemplateFunction, (FNativeFuncPtr)&FLuaInvoker::execCallLua, GReflectionRegistry.RegisterFunction(TemplateFunction));
}
}

// 重載函數
void OverrideUFunction(UFunction *Function, FNativeFuncPtr NativeFunc, void *Userdata, bool bInsertOpcodes)
{
Function->SetNativeFunc(NativeFunc);
if (Function->Script.Num() < 1)
{
if (bInsertOpcodes)
{
Function->Script.Add(EX_CallLua);
int32 Index = Function->Script.AddZeroed(sizeof(Userdata));
FMemory::Memcpy(Function->Script.GetData() + Index, &Userdata, sizeof(Userdata));
Function->Script.Add(EX_Return);
Function->Script.Add(EX_Nothing);
}
else
{
int32 Index = Function->Script.AddZeroed(sizeof(Userdata));
FMemory::Memcpy(Function->Script.GetData() + Index, &Userdata, sizeof(Userdata));
}
}
}

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章