209 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			209 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#pragma once
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#include <coreclr_delegates.h>
							 | 
						|||
| 
								 | 
							
								#include <hostfxr.h>
							 | 
						|||
| 
								 | 
							
								#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<UCSManager>(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<void(UPackage*)>& Callback) const
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										for (UPackage* Package : AllPackages)
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											Callback(Package);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									void ForEachManagedField(const TFunction<void(UObject*)>& 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<UDynamicSubsystem> 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<TObjectPtr<UPackage>> AllPackages;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									UPROPERTY()
							 | 
						|||
| 
								 | 
							
									TObjectPtr<UPackage> GlobalManagedPackage;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									UPROPERTY(Transient)
							 | 
						|||
| 
								 | 
							
									TArray<TSubclassOf<UDynamicSubsystem>> PendingDynamicSubsystemClasses;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									UPROPERTY(Transient)
							 | 
						|||
| 
								 | 
							
									TObjectPtr<UCSTypeBuilderManager> TypeBuilderManager;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// Handles to all active UObjects that has a C# counterpart. The key is the unique ID of the UObject.
							 | 
						|||
| 
								 | 
							
									TMap<uint32, TSharedPtr<FGCHandle>> 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<uint32, TMap<uint32, TSharedPtr<FGCHandle>>> ManagedInterfaceWrappers;
							 | 
						|||
| 
								 | 
							
									
							 | 
						|||
| 
								 | 
							
									// Map to cache assemblies that native classes are associated with, for quick lookup.
							 | 
						|||
| 
								 | 
							
									UPROPERTY()
							 | 
						|||
| 
								 | 
							
									TMap<uint32, TObjectPtr<UCSAssembly>> NativeClassToAssemblyMap;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									UPROPERTY()
							 | 
						|||
| 
								 | 
							
									TMap<FName, TObjectPtr<UCSAssembly>> LoadedAssemblies;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									TWeakObjectPtr<UObject> 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
							 | 
						|||
| 
								 | 
							
								};
							 |