Exemplo n.º 1
0
 public FunctionRedirect(IntPtr unrealClass, string dummyName, Delegate callback)
 {
     Debug.Assert(!Native_UStruct.IsChildOf(unrealClass, Runtime.Classes.UClass));
     Class     = unrealClass;
     DummyName = dummyName;
     Callback  = callback;
 }
Exemplo n.º 2
0
 public bool IsChildOf(UStruct someBase)
 {
     if (someBase == null)
     {
         return(false);
     }
     return(Native_UStruct.IsChildOf(Address, someBase.Address));
 }
Exemplo n.º 3
0
        /// <summary>
        /// Try and find boolean metadata with the given key. If not found on this class, work up hierarchy looking for it.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool GetBoolMetaDataHierarchical(FName key)
        {
#if WITH_EDITOR
            return(Native_UStruct.GetBoolMetaDataHierarchical(Address, ref key));
#else
            return(false);
#endif
        }
Exemplo n.º 4
0
 /// <summary>
 /// Returns the struct/ class prefix used for the C++ declaration of this struct/ class.
 /// </summary>
 /// <returns>Prefix character used for C++ declaration of this struct/ class.</returns>
 public string GetPrefixCPP()
 {
     using (FStringUnsafe resultUnsafe = new FStringUnsafe())
     {
         Native_UStruct.GetPrefixCPP(Address, ref resultUnsafe.Array);
         return(resultUnsafe.Value);
     }
 }
Exemplo n.º 5
0
        /// <summary>
        /// Try and find boolean metadata with the given key. If not found on this class, work up hierarchy looking for it.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool GetBoolMetaDataHierarchical(FName key)
        {
            // WITH_EDITOR
            if (Native_UStruct.GetBoolMetaDataHierarchical == null)
            {
                return(false);
            }

            return(Native_UStruct.GetBoolMetaDataHierarchical(Address, ref key));
        }
Exemplo n.º 6
0
        internal void Initialize()
        {
            EnsureNotInitialized();

            if (Address == IntPtr.Zero)
            {
                Address = FMemory.Malloc(NativeReflection.GetStructSize(structAddress));
                Native_UStruct.InitializeStruct(structAddress, Address, 1);
            }

            initialized = true;
        }
Exemplo n.º 7
0
        /// <summary>
        /// Try and find string metadata with the given key. If not found on this class, work up hierarchy looking for it.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="outValue"></param>
        /// <returns></returns>
        public bool GetStringMetaDataHierarchical(FName key, out string outValue)
        {
#if WITH_EDITOR
            using (FStringUnsafe outValueUnsafe = new FStringUnsafe())
            {
                bool result = Native_UStruct.GetStringMetaDataHierarchical(Address, ref key, ref outValueUnsafe.Array);
                outValue = outValueUnsafe.Value;
                return(result);
            }
#else
            outValue = null;
            return(false);
#endif
        }
Exemplo n.º 8
0
 internal void Destroy()
 {
     if (Address != IntPtr.Zero)
     {
         Native_UStruct.DestroyStruct(structAddress, Address, 1);
         if (selfAllocated)
         {
             FMemory.Free(Address);
         }
         Address       = IntPtr.Zero;
         initialized   = false;
         selfAllocated = false;
     }
 }
Exemplo n.º 9
0
        /// <summary>
        /// Try and find string metadata with the given key. If not found on this class, work up hierarchy looking for it.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="outValue"></param>
        /// <returns></returns>
        public bool GetStringMetaDataHierarchical(FName key, ref string outValue)
        {
            // WITH_EDITOR
            if (Native_UStruct.GetStringMetaDataHierarchical == null)
            {
                return(false);
            }

            using (FStringUnsafe outValueUnsafe = new FStringUnsafe(outValue))
            {
                bool result = Native_UStruct.GetStringMetaDataHierarchical(Address, ref key, ref outValueUnsafe.Array);
                outValue = outValueUnsafe.Value;
                return(result);
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Gets the first known managed type for a given UClass
        /// </summary>
        /// <param name="unrealClass">The UClass to get the managed type from</param>
        /// <param name="includeAbstract">Include abstract types (if true a wrapper cannot be instantiated from this type)</param>
        /// <returns>The managed type</returns>
        public static Type GetFirstKnownType(UClass unrealClass, bool includeAbstract = true)
        {
            Type   type = null;
            IntPtr unrealClassAddress = unrealClass.Address;

            while (type == null && unrealClassAddress != IntPtr.Zero)
            {
                classesByAddress.TryGetValue(unrealClassAddress, out type);
                if (type != null && !includeAbstract && type.IsAbstract)
                {
                    type = null;
                }
                unrealClassAddress = Native_UStruct.GetSuperStruct(unrealClassAddress);
            }
            return(type);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Create properties / functions and link the class
        /// </summary>
        public void Initialize()
        {
            Native_UStruct.Set_Children(StaticClass, IntPtr.Zero);

            BindingFlags propertyBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly;

            foreach (PropertyInfo property in Type.GetProperties(propertyBindingFlags))
            {
                if (property.GetCustomAttribute <USharpPathAttribute>() != null)
                {
                    CreateProperty(StaticClass, property);
                }
            }

            Native_UField.Bind(StaticClass);
            Native_UStruct.StaticLink(StaticClass, true);
            firstRun = false;
        }
Exemplo n.º 12
0
        private IntPtr FindProperty(string propertyName)
        {
            FName  fname    = new FName(propertyName);
            IntPtr property = Native_UStruct.FindPropertyByName(nativeClass, ref fname);

            if (!(FBuild.BuildShipping || FBuild.BuildTest))
            {
                if (property == IntPtr.Zero)
                {
                    FMessage.Log(FMessage.LogNet, ELogVerbosity.Fatal, $"Attempt to replicate property '{propertyName}' which does not exist.");
                }
                else if (!Native_UProperty.HasAnyPropertyFlags(property, EPropertyFlags.Net))
                {
                    FMessage.Log(FMessage.LogNet, ELogVerbosity.Fatal, $"Attempt to replicate property '{propertyName}' that was not tagged to replicate! Please use 'Replicated' or 'ReplicatedUsing' keyword in the UProperty() declaration.");
                }
            }

            return(property);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Validates that the given property exists and matches the given UProperty class (e.g. UBoolProperty::StaticClass())
        /// </summary>
        /// <param name="unrealStruct">The address of the structure which owns the property</param>
        /// <param name="propertyName">The name of the property</param>
        /// <param name="propertyClass">The expected UProperty class of the property</param>
        /// <returns></returns>
        public static bool ValidatePropertyClass(IntPtr unrealStruct, string propertyName, IntPtr propertyClass)
        {
            IntPtr field = FindField(unrealStruct, propertyName);

            if (field == IntPtr.Zero || !Native_UObjectBaseUtility.IsA(field, Classes.UProperty))
            {
                return(false);
            }
            IntPtr actualClass = Native_UObjectBase.GetClass(field);

            if (actualClass == propertyClass)
            {
                return(true);
            }
            if (actualClass != IntPtr.Zero && propertyClass == Classes.UEnumProperty &&
                Native_UStruct.IsChildOf(actualClass, Classes.UNumericProperty))
            {
                return(Native_UNumericProperty.IsEnum(field));
            }
            return(false);
        }
Exemplo n.º 14
0
 public UProperty FindPropertyByName(FName name)
 {
     return(GCHelper.Find <UProperty>(Native_UStruct.FindPropertyByName(Address, ref name)));
 }
Exemplo n.º 15
0
        /// <summary>
        /// Gets the first known type from a given UObject address (classes may be defined at runtime which we don't have a type mapping for.
        /// Look up the inheritance chain until we have a known type)
        /// </summary>
        /// <param name="objectAddress">The UObject address</param>
        /// <param name="isKnownType">True if the result is the exact type of the given UObject address</param>
        /// <param name="includeAbstract">Include abstract types (if true a wrapper cannot be instantiated from this type)</param>
        /// <returns>The first known managed type</returns>
        public static Type GetFirstKnownType(IntPtr objectAddress, out bool isKnownType, bool includeAbstract = true)
        {
            isKnownType = true;
            if (objectAddress == IntPtr.Zero)
            {
                return(null);
            }

            Type type = GetType(objectAddress);

            if (type != null && (!type.IsAbstract || includeAbstract))
            {
                return(type);
            }
            else
            {
                type = null;
            }

            IntPtr parentClassAddress = IntPtr.Zero;

            IntPtr unrealClassAddress = Native_UObjectBase.GetClass(objectAddress);

            if (unrealClassAddress == Classes.UClass)
            {
                // The objectAddress is already a class
                unrealClassAddress = objectAddress;
            }

            if (unrealClassAddress != IntPtr.Zero)
            {
                parentClassAddress = Native_UStruct.GetSuperStruct(unrealClassAddress);
            }

            while (type == null && parentClassAddress != IntPtr.Zero)
            {
                isKnownType = false;
                classesByAddress.TryGetValue(parentClassAddress, out type);
                if (type != null && type.IsAbstract && !includeAbstract)
                {
                    type = null;
                }
                parentClassAddress = Native_UStruct.GetSuperStruct(parentClassAddress);
            }

            if (type == null && unrealClassAddress != IntPtr.Zero)
            {
                // Some fallbacks
                if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UStruct))
                {
                    if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UClass))
                    {
                        if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UBlueprintGeneratedClass))
                        {
                            return(typeof(UBlueprintGeneratedClass));
                        }

                        return(typeof(UClass));
                    }

                    if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UScriptStruct))
                    {
                        if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UUserDefinedStruct))
                        {
                            return(typeof(UUserDefinedStruct));
                        }

                        return(typeof(UScriptStruct));
                    }

                    if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UEnum))
                    {
                        if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UUserDefinedEnum))
                        {
                            return(typeof(UUserDefinedEnum));
                        }

                        return(typeof(UEnum));
                    }

                    if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UFunction))
                    {
                        return(typeof(UFunction));
                    }

                    return(typeof(UStruct));
                }

                // UObject fallback (would expect this to always be true)
                if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UObject))
                {
                    return(typeof(UObject));
                }
            }

            return(type);
        }
Exemplo n.º 16
0
 /// <summary>
 /// Returns the size of the structure (use GetStructSize for getting the size of an actual struct)
 /// </summary>
 /// <returns></returns>
 public int GetStructureSize()
 {
     return(Native_UStruct.GetStructureSize(Address));
 }
Exemplo n.º 17
0
 /// <summary>
 /// Destroy a struct in memory. This may be done by calling the native destructor and then the constructor or individually reinitializing properties
 /// </summary>
 /// <param name="dest">Pointer to memory to destory</param>
 /// <param name="arrayDim">Number of elements in the array</param>
 public void DestroyStruct(IntPtr dest, int arrayDim)
 {
     Native_UStruct.DestroyStruct(Address, dest, arrayDim);
 }
Exemplo n.º 18
0
 /// <summary>
 /// Initialize a struct over uninitialized memory. This may be done by calling the native constructor or individually initializing properties
 /// </summary>
 /// <param name="dest">Pointer to memory to initialize</param>
 /// <param name="arrayDim">Number of elements in the array</param>
 public void InitializeStruct(IntPtr dest, int arrayDim)
 {
     Native_UStruct.InitializeStruct(Address, dest, arrayDim);
 }
Exemplo n.º 19
0
 public void TagSubobjects(EObjectFlags newFlags)
 {
     Native_UStruct.TagSubobjects(Address, newFlags);
 }
Exemplo n.º 20
0
 public void StaticLink(bool relinkExistingProperties)
 {
     Native_UStruct.StaticLink(Address, relinkExistingProperties);
 }
Exemplo n.º 21
0
            private unsafe void HandleInvokeFunctionFromBP(IntPtr obj, FFrame *stack, IntPtr result,
                                                           UFunction.FuncInvokerManaged managedFunctionInvoker)
            {
                // NOTE: ScriptCore.cpp uses PropertiesSize instead of ParamsSize. Is it ever any different? (it says alignment
                // may make them different) If it is different we should probably use PropertiesSize (including in generated code /
                // IL) as ScriptCore.cpp uses a memcpy of our memory.
                Debug.Assert(Native_UStruct.Get_PropertiesSize(stack->CurrentNativeFunction) ==
                             Native_UFunction.Get_ParmsSize(stack->CurrentNativeFunction));

                IntPtr function     = stack->CurrentNativeFunction;
                int    paramsSize   = Native_UFunction.Get_ParmsSize(function);
                int    numParams    = Native_UFunction.Get_NumParms(function);
                bool   hasOutParams = Native_UFunction.HasAnyFunctionFlags(function, EFunctionFlags.HasOutParms);

                IntPtr *outParamsBufferPtr = stackalloc IntPtr[numParams];

                byte * paramsBufferPtr = stackalloc byte[paramsSize];
                IntPtr paramsBuffer    = (IntPtr)paramsBufferPtr;

                // We could skip this memzero as stackalloc will (always?) zero memory even though the spec states
                // "The content of the newly allocated memory is undefined."
                // https://github.com/dotnet/coreclr/issues/1279
                FMemory.Memzero(paramsBuffer, paramsSize);

                if (hasOutParams)
                {
                    int paramIndex = 0;
                    foreach (IntPtr param in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function, false))
                    {
                        // Not required but using for Debug.Assert() when getting the value
                        stack->MostRecentPropertyAddress = IntPtr.Zero;

                        stack->Step(stack->Object, paramsBuffer + Native_UProperty.GetOffset_ForUFunction(param));
                        outParamsBufferPtr[paramIndex] = stack->MostRecentPropertyAddress;

                        if (Native_UProperty.HasAnyPropertyFlags(param, EPropertyFlags.ReturnParm))
                        {
                            // This should be UObject::execEndFunctionParms which will just do "stack->Code--;" for allowing
                            // the caller to use PFINISH aftwards
                            outParamsBufferPtr[paramIndex] = result;
                        }

                        paramIndex++;
                    }
                }
                else
                {
                    foreach (IntPtr param in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function, false))
                    {
                        stack->Step(stack->Object, paramsBuffer + Native_UProperty.GetOffset_ForUFunction(param));
                    }
                }
                stack->PFinish();// Skip EX_EndFunctionParms

                // Call the managed function invoker which will marshal the params from the native params buffer and then call the
                // target managed function
                managedFunctionInvoker(paramsBuffer, obj);

                // Copy out params from the temp buffer
                if (hasOutParams)
                {
                    int paramIndex = 0;
                    foreach (IntPtr paramProp in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function, false))
                    {
                        if (Native_UProperty.HasAnyPropertyFlags(paramProp, EPropertyFlags.OutParm))
                        {
                            Debug.Assert(outParamsBufferPtr[paramIndex] != IntPtr.Zero);

                            // - See "REMOVING the DestroyValue call" below.
                            // Destroy the existing memory (this assumed the existing memory is valid or at least memzerod)
                            //Native_UProperty.DestroyValue(paramProp, outParamsBufferPtr[paramIndex]);

                            // A raw memcpy should be OK since the managed invoker should have set this memory appropriately.
                            FMemory.Memcpy(outParamsBufferPtr[paramIndex],
                                           paramsBuffer + Native_UProperty.GetOffset_ForUFunction(paramProp),
                                           Native_UProperty.Get_ElementSize(paramProp));// Should be ArrayDim*ElementSize but ArrayDim should always be 1 for params
                        }
                        paramIndex++;
                    }
                }

                // Parameters are copied when calling stack->Step(). We are responsible for destroying non-blittable types
                // which were copied (FString, TArray, etc). For C++ this works out well due to the copy constructors etc.
                //
                // Example where an FString is constructed from stack->Step():
                // UObject::execStringConst(...) { *(FString*)RESULT_PARAM = (ANSICHAR*)Stack.Code; }
                //
                // For C# it might be better if we reimplemented all of the IMPLEMENT_VM_FUNCTION functions to reduce the amount
                // of copying as we currently need ANOTHER copy to get it from the temp buffer into a C# type (which is done
                // inside the managedFunctionInvoker function)
                foreach (IntPtr paramProp in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function,
                                                                                      EFieldIteratorType.Destructor, false))
                {
                    // When is this ever false? It seems to be checked in UObject::ProcessEvent()
                    // "Destroy local variables except function parameters." - used for BP locals?
                    Debug.Assert(Native_UProperty.IsInContainer(paramProp, paramsSize));

                    // Out params are copied to the memory maintained by the caller so only destroy "by value" parameters.
                    if (!Native_UProperty.HasAnyPropertyFlags(paramProp, EPropertyFlags.OutParm))
                    {
                        Native_UProperty.DestroyValue_InContainer(paramProp, paramsBuffer);
                    }
                }
            }
Exemplo n.º 22
0
 public UStruct GetInheritanceSuper()
 {
     return(GCHelper.Find <UStruct>(Native_UStruct.GetInheritanceSuper(Address)));
 }
Exemplo n.º 23
0
        public static ManagedUnrealClass CreateClass(Type type)
        {
            ManagedUnrealClass existingClass = FindClass(type);

            if (existingClass != null)
            {
                if (!FBuild.WithHotReload)
                {
                    // TODO: Add support for hotreloading C# classes when WITH_HOT_RELOAD isn't available
                    // - WITH_HOT_RELOAD will be false on shipping, monolithic and server builds
                    // - Would need to make a copy of FHotReloadClassReinstancer (or just use it directly if
                    //   it doesn't depend on WITH_HOT_RELOAD and gets compiled into builds)
                    // - Would likely break blueprint classes which depend on any C# classes reinstanced in this way
                    return(existingClass);
                }

                existingClass.Clear();
                HotReloadClassCount++;
            }

            if (!type.IsSubclassOf(typeof(UObject)))
            {
                return(null);
            }

            USharpPathAttribute pathAttribute = type.GetCustomAttribute <USharpPathAttribute>();

            if (pathAttribute == null || string.IsNullOrEmpty(pathAttribute.Path))
            {
                return(null);
            }

            IntPtr parentClass = GetStaticClass(type.BaseType);

            if (parentClass == IntPtr.Zero)
            {
                return(null);
            }

            string root, directory, moduleName, className, memberName;

            FPackageName.GetPathInfo(pathAttribute.Path, out root, out directory, out moduleName, out className, out memberName);

            string packageName = "/" + root + "/" + directory;

            if (string.IsNullOrEmpty(moduleName) || string.IsNullOrEmpty(className))
            {
                return(null);
            }

            IntPtr package = NativeReflection.FindObject(Native_UPackage.StaticClass(), IntPtr.Zero, packageName, true);

            if (package == IntPtr.Zero)
            {
                package = NativeReflection.CreatePackage(IntPtr.Zero, packageName);
                Native_UPackage.SetPackageFlags(package, EPackageFlags.CompiledIn);

                // TODO: Find how to create a proper guid for a package (UHT CodeGenerator.cpp seems to use a crc of generated code)
                using (System.Security.Cryptography.SHA256 sha256 = System.Security.Cryptography.SHA256.Create())
                {
                    byte[] hash = sha256.ComputeHash(Encoding.ASCII.GetBytes(packageName));

                    // Truncate the hash
                    byte[] buffer = new byte[16];
                    Buffer.BlockCopy(hash, 0, buffer, 0, buffer.Length);

                    Native_UPackage.SetGuid(package, new Guid(buffer));
                }
            }

            ManagedUnrealClass managedUnrealClass = null;

            if (existingClass != null)
            {
                managedUnrealClass = existingClass;
            }
            else
            {
                managedUnrealClass = new ManagedUnrealClass(type, packageName, className, parentClass);
            }

            managedUnrealClass.StaticClass = USharpClass.CreateClassPtr(
                managedUnrealClass.PackageName,
                managedUnrealClass.ClassName,
                (uint)Native_UStruct.GetPropertiesSize(managedUnrealClass.ParentClass),
                EClassFlags.None,
                EClassCastFlags.None,
                managedUnrealClass.ConfigName,
                managedUnrealClass.ParentClass,
                managedUnrealClass.WithinClass,
                managedUnrealClass.ClassConstructor,
                managedUnrealClass.ClassVTableHelperCtorCaller,
                managedUnrealClass.ClassAddReferencedObjects);

            Native_UObjectBase.UObjectForceRegistration(managedUnrealClass.StaticClass);

            if (existingClass == null)
            {
                Classes.Add(type, managedUnrealClass);
                ClassesByAddress.Add(managedUnrealClass.StaticClass, managedUnrealClass);
            }

            managedUnrealClass.Initialize();

            return(managedUnrealClass);
        }