#pragma once #include #include #include "CSAssembly.h" #include "CSManagedCallbacksCache.h" #include "CSManager.generated.h" class UCSTypeBuilderManager; class UCSInterface; class UCSEnum; class UCSScriptStruct; class FUnrealSharpCoreModule; class UFunctionsExporter; struct FCSNamespace; struct FCSTypeReferenceMetaData; struct FCSManagedPluginCallbacks { using LoadPluginCallback = FGCHandleIntPtr(__stdcall*)(const TCHAR*, bool); using UnloadPluginCallback = bool(__stdcall*)(const TCHAR*); LoadPluginCallback LoadPlugin = nullptr; UnloadPluginCallback UnloadPlugin = nullptr; }; using FInitializeRuntimeHost = bool (*)(const TCHAR*, const TCHAR*, FCSManagedPluginCallbacks*, const void*, FCSManagedCallbacks::FManagedCallbacks*); DECLARE_MULTICAST_DELEGATE_OneParam(FOnManagedAssemblyLoaded, const FName&); DECLARE_MULTICAST_DELEGATE_OneParam(FOnManagedAssemblyUnloaded, const FName&); DECLARE_MULTICAST_DELEGATE(FOnAssembliesReloaded); DECLARE_MULTICAST_DELEGATE_OneParam(FCSClassEvent, UCSClass*); DECLARE_MULTICAST_DELEGATE_OneParam(FCSStructEvent, UCSScriptStruct*); DECLARE_MULTICAST_DELEGATE_OneParam(FCSInterfaceEvent, UCSInterface*); DECLARE_MULTICAST_DELEGATE_OneParam(FCSEnumEvent, UCSEnum*); UCLASS() class UNREALSHARPCORE_API UCSManager : public UObject, public FUObjectArray::FUObjectDeleteListener { GENERATED_BODY() public: static UCSManager& GetOrCreate() { if (!Instance) { Instance = NewObject(GetTransientPackage(), TEXT("CSManager"), RF_Public | RF_MarkAsRootSet); } return *Instance; } static UCSManager& Get() { return *Instance; } // The outermost package for all managed packages. If namespace support is off, this is the only package that will be used. UPackage* GetGlobalManagedPackage() const { return GlobalManagedPackage; } UPackage* FindOrAddManagedPackage(FCSNamespace Namespace); UCSAssembly* LoadAssemblyByPath(const FString& AssemblyPath, bool bIsCollectible = true); // Load an assembly by name that exists in the ProjectRoot/Binaries/Managed folder UCSAssembly* LoadUserAssemblyByName(const FName AssemblyName, bool bIsCollectible = true); // Load an assembly by name that exists in the UnrealSharp/Binaries/Managed folder UCSAssembly* LoadPluginAssemblyByName(const FName AssemblyName, bool bIsCollectible = true); UCSAssembly* FindOwningAssembly(UClass* Class); UCSAssembly* FindOwningAssembly(UScriptStruct* Struct); UCSAssembly* FindOwningAssembly(UEnum* Enum); UCSAssembly* FindAssembly(FName AssemblyName) const { return LoadedAssemblies.FindRef(AssemblyName); } UCSAssembly* FindOrLoadAssembly(FName AssemblyName) { if (UCSAssembly* Assembly = FindAssembly(AssemblyName)) { return Assembly; } return LoadUserAssemblyByName(AssemblyName); } FGCHandle FindManagedObject(const UObject* Object); FGCHandle FindOrCreateManagedInterfaceWrapper(UObject* Object, UClass* InterfaceClass); void SetCurrentWorldContext(UObject* WorldContext) { CurrentWorldContext = WorldContext; } UObject* GetCurrentWorldContext() const { return CurrentWorldContext.Get(); } const FCSManagedPluginCallbacks& GetManagedPluginsCallbacks() const { return ManagedPluginsCallbacks; } FOnManagedAssemblyLoaded& OnManagedAssemblyLoadedEvent() { return OnManagedAssemblyLoaded; } FOnManagedAssemblyUnloaded& OnManagedAssemblyUnloadedEvent() { return OnManagedAssemblyUnloaded; } FOnAssembliesReloaded& OnAssembliesLoadedEvent() { return OnAssembliesLoaded; } #if WITH_EDITOR FCSClassEvent& OnNewClassEvent() { return OnNewClass; } FCSStructEvent& OnNewStructEvent() { return OnNewStruct; } FCSInterfaceEvent& OnNewInterfaceEvent() { return OnNewInterface; } FCSEnumEvent& OnNewEnumEvent() { return OnNewEnum; } FSimpleMulticastDelegate& OnProcessedPendingClassesEvent() { return OnProcessedPendingClasses; } #endif void ForEachManagedPackage(const TFunction& Callback) const { for (UPackage* Package : AllPackages) { Callback(Package); } } void ForEachManagedField(const TFunction& Callback) const; bool IsManagedPackage(const UPackage* Package) const { return AllPackages.Contains(Package); } UPackage* GetPackage(const FCSNamespace Namespace); bool IsManagedType(const UObject* Field) const { return IsManagedPackage(Field->GetOutermost()); } bool IsLoadingAnyAssembly() const; void AddDynamicSubsystemClass(TSubclassOf SubsystemClass); UCSTypeBuilderManager* GetTypeBuilderManager() const { return TypeBuilderManager; } private: friend UCSAssembly; friend FUnrealSharpCoreModule; void Initialize(); static void Shutdown() { Instance = nullptr; } load_assembly_and_get_function_pointer_fn InitializeNativeHost() const; bool LoadRuntimeHost(); bool InitializeDotNetRuntime(); bool LoadAllUserAssemblies(); // UObjectArray listener interface virtual void NotifyUObjectDeleted(const UObjectBase* Object, int32 Index) override; virtual void OnUObjectArrayShutdown() override { GUObjectArray.RemoveUObjectDeleteListener(this); } void OnEnginePreExit() { GUObjectArray.RemoveUObjectDeleteListener(this); } // End of interface void OnModulesChanged(FName InModuleName, EModuleChangeReason InModuleChangeReason); void TryInitializeDynamicSubsystems(); UCSAssembly* FindOwningAssemblySlow(UField* Field); static UCSManager* Instance; UPROPERTY() TArray> AllPackages; UPROPERTY() TObjectPtr GlobalManagedPackage; UPROPERTY(Transient) TArray> PendingDynamicSubsystemClasses; UPROPERTY(Transient) TObjectPtr TypeBuilderManager; // Handles to all active UObjects that has a C# counterpart. The key is the unique ID of the UObject. TMap> ManagedObjectHandles; // Handles all active UObjects that have interface wrappers in C#. The primary key is the unique ID of the UObject. // The second key is the unique ID of the interface class. TMap>> ManagedInterfaceWrappers; // Map to cache assemblies that native classes are associated with, for quick lookup. UPROPERTY() TMap> NativeClassToAssemblyMap; UPROPERTY() TMap> LoadedAssemblies; TWeakObjectPtr CurrentWorldContext; FOnManagedAssemblyLoaded OnManagedAssemblyLoaded; FOnManagedAssemblyUnloaded OnManagedAssemblyUnloaded; FOnAssembliesReloaded OnAssembliesLoaded; #if WITH_EDITORONLY_DATA FCSClassEvent OnNewClass; FCSStructEvent OnNewStruct; FCSInterfaceEvent OnNewInterface; FCSEnumEvent OnNewEnum; FSimpleMulticastDelegate OnProcessedPendingClasses; #endif FCSManagedPluginCallbacks ManagedPluginsCallbacks; //.NET Core Host API hostfxr_initialize_for_dotnet_command_line_fn Hostfxr_Initialize_For_Dotnet_Command_Line = nullptr; hostfxr_initialize_for_runtime_config_fn Hostfxr_Initialize_For_Runtime_Config = nullptr; hostfxr_get_runtime_delegate_fn Hostfxr_Get_Runtime_Delegate = nullptr; hostfxr_close_fn Hostfxr_Close = nullptr; void* RuntimeHost = nullptr; //End };