private static bool StructHasGetTypeHash(IntPtr unrealStruct) { if (Native_UObjectBaseUtility.IsNative(unrealStruct)) { IntPtr cppStructOps = Native_UScriptStruct.GetCppStructOps(unrealStruct); return(cppStructOps != IntPtr.Zero && Native_ICppStructOps.HasGetTypeHash(cppStructOps)); } else { // if every member can be hashed (or is a UBoolProperty, which is specially // handled by UScriptStruct::GetStructTypeHash) then we can hash the struct: var fieldIterator = new NativeReflection.NativeFieldIterator(Classes.UProperty, unrealStruct); foreach (IntPtr property in fieldIterator) { if (Native_UObjectBaseUtility.IsA(property, Classes.UBoolProperty)) { continue; } else { if (!PropertyHasGetTypeHash(property)) { return(false); } } } return(true); } }
/// <summary> /// Compare this structure /// </summary> /// <returns>true if the copy was handled, otherwise it will fall back to UStructProperty::Identical</returns> public bool Identical(IntPtr a, IntPtr b, uint portFlags, out bool outResult) { csbool outResultTemp; bool result = Native_ICppStructOps.Identical(Address, a, b, portFlags, out outResultTemp); outResult = outResultTemp; return(result); }
/// <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); }
/// <summary> /// Call the C++ destructor /// </summary> public void Destruct(IntPtr dest) { Native_ICppStructOps.Destruct(Address, dest); }
/// <summary> /// Calls GetTypeHash if enabled /// </summary> public uint GetTypeHash(IntPtr src) { return(Native_ICppStructOps.GetTypeHash(Address, src)); }
/// <summary> /// Copy this structure /// </summary> /// <returns>true if the copy was handled, otherwise it will fall back to CopySingleValue</returns> public bool Copy(IntPtr dest, IntPtr src, int arrayDim) { return(Native_ICppStructOps.Copy(Address, dest, src, arrayDim)); }