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
|
|
};
|