/// <summary> /// Returns the size of the struct using ICppStructOps, otherwise falls back to GetStructureSize(). /// </summary> /// <returns></returns> public int GetStructSize() { UScriptStruct scriptStruct = this as UScriptStruct; if (scriptStruct != null) { IntPtr cppStructOps = Native_UScriptStruct.GetCppStructOps(scriptStruct.Address); if (cppStructOps != IntPtr.Zero) { return(Native_ICppStructOps.GetSize(cppStructOps)); } } return(GetStructureSize()); }
/// <summary> /// Checks if the given UScriptStruct address is POD and has a zero constructor (initializes to zero). /// /// NOTE: A struct could be PlainOldData but unsafe to zero initialize due to having a non-zero constructor / EForceInit constructor. /// </summary> internal static bool IsPODZeroInit(IntPtr unrealStruct) { if (unrealStruct != IntPtr.Zero && Native_UObjectBaseUtility.IsA(unrealStruct, Classes.UScriptStruct)) { EStructFlags structFlags = Native_UScriptStruct.Get_StructFlags(unrealStruct); IntPtr cppStructOps = Native_UScriptStruct.GetCppStructOps(unrealStruct); if (cppStructOps != IntPtr.Zero) { bool isPlainOldData = Native_ICppStructOps.IsPlainOldData(cppStructOps); bool hasZeroConstructor = Native_ICppStructOps.HasZeroConstructor(cppStructOps); bool hasNoopConstructor = Native_ICppStructOps.HasNoopConstructor(cppStructOps); if (!hasZeroConstructor && structFlags.HasFlag(EStructFlags.ZeroConstructor)) { // This struct flag could have been set in the zero constructor check in UScriptStruct::PrepareCppStructOps hasZeroConstructor = true; } if (isPlainOldData && hasZeroConstructor && !hasNoopConstructor) { return(true); } if (isPlainOldData && !hasZeroConstructor) { if (hasNoopConstructor) { // The struct has a no-op constructor and takes EForceInit to init return(false); } // This is a copy of a check made in UScriptStruct::PrepareCppStructOps to check if the struct constructs to zero // if (CppStructOps->IsPlainOldData() && !CppStructOps->HasZeroConstructor()) { ... } int size = Native_ICppStructOps.GetSize(cppStructOps); IntPtr buffer = FMemory.Malloc(size); FMemory.Memzero(buffer, size); Native_ICppStructOps.Construct(cppStructOps, buffer); Native_ICppStructOps.Construct(cppStructOps, buffer);// slightly more like to catch "internal counters" if we do this twice bool isZeroConstruct = true; unsafe { byte *bufferPtr = (byte *)buffer; for (int i = 0; i < size; i++) { if (bufferPtr[i] != 0) { isZeroConstruct = false; break; } } } FMemory.Free(buffer); if (isZeroConstruct) { // "Native struct %s has DISCOVERED zero construction. Size = %d" System.Diagnostics.Debugger.Break(); return(true); } } return(false); } else { // Only treat it as blittable if it is POD and has a zero constructor return(structFlags.HasFlag(EStructFlags.IsPlainOldData | EStructFlags.ZeroConstructor)); } } return(false); }