mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Start CoreClr from Beef and basic interaction
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
FileVersion = 1
|
||||
Dependencies = {GlitchLog = "*", corlib = "*", DirectX = "*", FreeType = "*", cgltf-beef = "*", msdfgen-beef = "*", ImGui = "*", ImGuiImplDX11 = "*", ImGuiImplWin32 = "*", ImGuizmo = "*", Beefy2D = "*", LodePng = "*", GlitchyEngineHelper = "*", bon = "*", box2d-beef = "*", "Beef.Linq" = "*"}
|
||||
Dependencies = {GlitchLog = "*", corlib = "*", DirectX = "*", FreeType = "*", cgltf-beef = "*", msdfgen-beef = "*", ImGui = "*", ImGuiImplDX11 = "*", ImGuiImplWin32 = "*", ImGuizmo = "*", Beefy2D = "*", LodePng = "*", GlitchyEngineHelper = "*", bon = "*", box2d-beef = "*", "Beef.Linq" = "*", NetHostBeef = "*"}
|
||||
|
||||
[Project]
|
||||
Name = "GlitchyEngine"
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
using NetHostBeef;
|
||||
using System;
|
||||
using System.Interop;
|
||||
|
||||
namespace GlitchyEngine.Scripting;
|
||||
|
||||
static class CoreClrHelper
|
||||
{
|
||||
static HostFxr.InitializeForDotnetCommandLineFn HostFxr_Init;
|
||||
static HostFxr.GetRuntimeDelegateFn HostFxr_GetDelegate;
|
||||
static HostFxr.CloseFn HostFxr_Close;
|
||||
|
||||
static CoreClr.LoadAssemblyAndGetFunctionPointerFn LoadAssemblyAndGetFunctionPointerFn;
|
||||
static CoreClr.GetFunctionPointerFn GetFunctionPointerFn;
|
||||
|
||||
private function void LoadScriptAssemblyFunc(uint8* appData, int64 appLength, uint8* pdbData, int64 pdbLength);
|
||||
|
||||
//static function void(char8* path) LoadScriptAssembly;
|
||||
static LoadScriptAssemblyFunc _loadScriptAssembly;
|
||||
static function void() _unloadAssemblies;
|
||||
|
||||
public static void Init(StringView coreAssemblyPath)
|
||||
{
|
||||
LoadHostFxr();
|
||||
InitAndStartRuntime(coreAssemblyPath);
|
||||
|
||||
PrepareFunction();
|
||||
}
|
||||
|
||||
static void LoadHostFxr()
|
||||
{
|
||||
char_t[256] buffer = ?;
|
||||
c_size bufferSize = buffer.Count;
|
||||
int rc = NetHost.get_hostfxr_path(&buffer, &bufferSize, null);
|
||||
|
||||
Log.EngineLogger.AssertDebug(rc == 0, "Failed to get HostFxr path.");
|
||||
|
||||
// Load hostfxr and get desired exports
|
||||
void* lib = NetHostHelper.LoadLibrary(&buffer);
|
||||
HostFxr_Init = NetHostHelper.GetExport<HostFxr.InitializeForDotnetCommandLineFn>(lib, "hostfxr_initialize_for_dotnet_command_line");
|
||||
HostFxr_GetDelegate = NetHostHelper.GetExport<HostFxr.GetRuntimeDelegateFn>(lib, "hostfxr_get_runtime_delegate");
|
||||
HostFxr_Close = NetHostHelper.GetExport<HostFxr.CloseFn>(lib, "hostfxr_close");
|
||||
|
||||
Log.EngineLogger.AssertDebug(HostFxr_Init != null && HostFxr_GetDelegate != null && HostFxr_Close != null, "Retrieving at least one HostFxr function failed.");
|
||||
}
|
||||
|
||||
static void InitAndStartRuntime(StringView coreAssembly)
|
||||
{
|
||||
char_t* ptr = NetHostHelper.GetScopedRawPtr!(coreAssembly);
|
||||
|
||||
char_t*[2] args = char_t*[](
|
||||
ptr,
|
||||
null
|
||||
);
|
||||
|
||||
HostFxr.Handle cxt = null;
|
||||
int rc = HostFxr_Init(1, &args, null, &cxt);
|
||||
|
||||
if (rc != 0 || cxt == null)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to initialize HostFxr: {rc}");
|
||||
HostFxr_Close(cxt);
|
||||
}
|
||||
|
||||
Log.EngineLogger.Assert(rc == 0, "Failed to initialize HostFxr.");
|
||||
|
||||
rc = HostFxr_GetDelegate(cxt, .LoadAssemblyAndGetFunctionPointer, (void**)&LoadAssemblyAndGetFunctionPointerFn);
|
||||
|
||||
Log.EngineLogger.Assert(rc == 0, scope $"Get delegate failed: {rc}. (LoadAssemblyAndGetFunctionPointer)");
|
||||
|
||||
rc = HostFxr_GetDelegate(cxt, .GetFunctionPointer, (void**)&GetFunctionPointerFn);
|
||||
|
||||
Log.EngineLogger.Assert(rc == 0, scope $"Get delegate failed: {rc}. (GetFunctionPointer)");
|
||||
|
||||
HostFxr_Close(cxt);
|
||||
}
|
||||
|
||||
static void PrepareFunction()
|
||||
{
|
||||
GetFunctionPointerUnmanagedCallersOnly<LoadScriptAssemblyFunc>("GlitchyEngine.ScriptGlue, ScriptCore", "LoadScriptAssembly",
|
||||
out _loadScriptAssembly);
|
||||
|
||||
GetFunctionPointerUnmanagedCallersOnly<function void()>("GlitchyEngine.ScriptGlue, ScriptCore", "UnloadAssemblies",
|
||||
out _unloadAssemblies);
|
||||
}
|
||||
|
||||
public static void LoadAppAssembly(Span<uint8> appAssemblyData, Span<uint8> pdbData)
|
||||
{
|
||||
_loadScriptAssembly(appAssemblyData.Ptr, appAssemblyData.Length, pdbData.Ptr, pdbData.Length);
|
||||
}
|
||||
|
||||
public static void UnloadAssemblies()
|
||||
{
|
||||
_unloadAssemblies();
|
||||
}
|
||||
|
||||
public static int GetFunctionPointer<T>(StringView typeName, StringView methodName, StringView delegateName, out T outDelegate) where T: operator explicit void*
|
||||
{
|
||||
void* funPtr = null;
|
||||
|
||||
int rc = GetFunctionPointerFn(NetHostHelper.GetScopedRawPtr!(typeName),
|
||||
NetHostHelper.GetScopedRawPtr!(methodName), NetHostHelper.GetScopedRawPtr!(delegateName),
|
||||
null, null, out funPtr);
|
||||
|
||||
outDelegate = (T)funPtr;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static int GetFunctionPointerDefaultDelegate(StringView typeName, StringView methodName, out CoreClr.DefaultEntryPoint outDelegate)
|
||||
{
|
||||
void* funPtr = null;
|
||||
|
||||
int rc = GetFunctionPointerFn(NetHostHelper.GetScopedRawPtr!(typeName),
|
||||
NetHostHelper.GetScopedRawPtr!(methodName), null, null, null, out funPtr);
|
||||
|
||||
outDelegate = (CoreClr.DefaultEntryPoint)funPtr;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static int GetFunctionPointerUnmanagedCallersOnly<T>(StringView typeName, StringView methodName, out T outDelegate) where T: operator explicit void*
|
||||
{
|
||||
void* funPtr = null;
|
||||
|
||||
int rc = GetFunctionPointerFn(NetHostHelper.GetScopedRawPtr!(typeName),
|
||||
NetHostHelper.GetScopedRawPtr!(methodName), CoreClr.UNMANAGEDCALLERSONLY_METHOD, null, null, out funPtr);
|
||||
|
||||
outDelegate = (T)funPtr;
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ using System.Collections;
|
||||
using GlitchyEngine.Core;
|
||||
using GlitchyEngine.Math;
|
||||
using GlitchyEngine.World;
|
||||
using NetHostBeef;
|
||||
using System.Interop;
|
||||
|
||||
namespace GlitchyEngine.Scripting;
|
||||
|
||||
@@ -96,49 +98,32 @@ static class ScriptEngine
|
||||
{
|
||||
internal static MonoClass* s_ShowInEditorAttribute;
|
||||
}
|
||||
|
||||
private static String _coreAssemblyPath = "resources/scripts/ScriptCore.dll";
|
||||
private static String _appAssemblyPath = "SandboxProject/Assets/Scripts/bin/Sandbox.dll";
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
InitMono();
|
||||
ScriptGlue.Init();
|
||||
CoreClrHelper.Init(_coreAssemblyPath);
|
||||
|
||||
//ScriptGlue.Init();
|
||||
|
||||
LoadScriptAssemblies();
|
||||
LoadScriptAssembly();
|
||||
|
||||
InitAssemblyWatcher();
|
||||
}
|
||||
|
||||
static void InitMono()
|
||||
{
|
||||
Mono.mono_set_assemblies_path("mono/lib");
|
||||
|
||||
if (_debuggingEnabled)
|
||||
{
|
||||
char8*[2] options = .(
|
||||
"--debugger-agent=transport=dt_socket,address=127.0.0.1:2550,server=y,suspend=n,loglevel=3,logfile=MonoDebugger.log",
|
||||
"--soft-breakpoints"
|
||||
);
|
||||
|
||||
Mono.mono_jit_parse_options(options.Count, &options);
|
||||
Mono.mono_debug_init(.Mono);
|
||||
}
|
||||
|
||||
s_RootDomain = Mono.mono_jit_init("GlitchyEngineJITRuntime");
|
||||
Log.EngineLogger.Assert(s_RootDomain != null, "Failed to initialize mono root domain");
|
||||
|
||||
if (_debuggingEnabled)
|
||||
{
|
||||
Mono.mono_debug_domain_create(s_RootDomain);
|
||||
}
|
||||
|
||||
Mono.mono_thread_set_main(Mono.mono_thread_current());
|
||||
}
|
||||
|
||||
static void InitAssemblyWatcher()
|
||||
{
|
||||
if (_userAssemblyWatcher == null)
|
||||
{
|
||||
String directoryPath = scope String();
|
||||
Path.GetDirectoryPath(_appAssemblyPath, directoryPath);
|
||||
String fileName = scope String();
|
||||
Path.GetFileName(_appAssemblyPath, fileName);
|
||||
|
||||
// TODO: Obviously don't hardcode path
|
||||
_userAssemblyWatcher = new FileSystemWatcher("SandboxProject/Assets/Scripts/bin/", "*/Sandbox.dll");
|
||||
_userAssemblyWatcher = new FileSystemWatcher(directoryPath, fileName);
|
||||
_userAssemblyWatcher.OnChanged.Add(new (fileName) =>
|
||||
{
|
||||
// TODO: Temporary, we want to be able to reload while in play-mode. (+ Editor Scripts will be a thing some day)
|
||||
@@ -165,7 +150,7 @@ static class ScriptEngine
|
||||
_userAssemblyWatcher.StartRaisingEvents();
|
||||
}
|
||||
|
||||
static void LoadScriptAssemblies()
|
||||
/*static void LoadScriptAssemblies()
|
||||
{
|
||||
CreateAppDomain("GlitchyEngineScriptRuntime");
|
||||
(s_CoreAssembly, s_CoreAssemblyImage) = LoadAssembly("resources/scripts/ScriptCore.dll", _debuggingEnabled);
|
||||
@@ -174,6 +159,28 @@ static class ScriptEngine
|
||||
GetEntitiesFromAssemblies();
|
||||
|
||||
ScriptGlue.RegisterManagedComponents();
|
||||
}*/
|
||||
|
||||
static void LoadScriptAssembly()
|
||||
{
|
||||
List<uint8> data = new List<uint8>(1024);
|
||||
File.ReadAll(_appAssemblyPath, data);
|
||||
|
||||
List<uint8> pdbData = new List<uint8>(1024);
|
||||
|
||||
String pdbPath = scope .();
|
||||
Path.ChangeExtension(_appAssemblyPath, ".pdb", pdbPath);
|
||||
|
||||
File.ReadAll(pdbPath, pdbData);
|
||||
|
||||
CoreClrHelper.LoadAppAssembly(data, pdbData);
|
||||
|
||||
delete data;
|
||||
delete pdbData;
|
||||
|
||||
//GetEntitiesFromAssemblies();
|
||||
|
||||
//ScriptGlue.RegisterManagedComponents();
|
||||
}
|
||||
|
||||
public static void SetContext(Scene scene)
|
||||
@@ -351,11 +358,14 @@ static class ScriptEngine
|
||||
{
|
||||
Debug.Profiler.ProfileFunction!();
|
||||
|
||||
Mono.mono_domain_set(s_RootDomain, false);
|
||||
CoreClrHelper.UnloadAssemblies();
|
||||
LoadScriptAssembly();
|
||||
|
||||
Mono.mono_domain_unload(s_AppDomain);
|
||||
//Mono.mono_domain_set(s_RootDomain, false);
|
||||
|
||||
LoadScriptAssemblies();
|
||||
//Mono.mono_domain_unload(s_AppDomain);
|
||||
|
||||
//LoadScriptAssemblies();
|
||||
|
||||
// TODO: ScriptFields might get added
|
||||
// TODO: ScriptField Types may change after reload!
|
||||
@@ -367,13 +377,13 @@ static class ScriptEngine
|
||||
|
||||
public static void Shutdown()
|
||||
{
|
||||
Mono.mono_domain_set(s_RootDomain, false);
|
||||
/*Mono.mono_domain_set(s_RootDomain, false);
|
||||
|
||||
Mono.mono_domain_unload(s_AppDomain);
|
||||
s_AppDomain = null;
|
||||
|
||||
Mono.mono_jit_cleanup(s_RootDomain);
|
||||
s_RootDomain = null;
|
||||
s_RootDomain = null;*/
|
||||
}
|
||||
|
||||
internal static void RegisterSharpType(SharpType sharpType)
|
||||
|
||||
@@ -29,7 +29,7 @@ static class ScriptGlue
|
||||
}
|
||||
}
|
||||
|
||||
/* Adding this attribute to a method will log method entry and returned Result<T> errors */
|
||||
/*/* Adding this attribute to a method will log method entry and returned Result<T> errors */
|
||||
[AttributeUsage(.Method)]
|
||||
struct RegisterMethodAttribute : Attribute, IOnMethodInit
|
||||
{
|
||||
@@ -48,13 +48,13 @@ static class ScriptGlue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
RegisterCalls();
|
||||
//RegisterCalls();
|
||||
|
||||
RegisterMathFunctions();
|
||||
//RegisterMathFunctions();
|
||||
}
|
||||
|
||||
public static void RegisterManagedComponents()
|
||||
@@ -67,11 +67,11 @@ static class ScriptGlue
|
||||
RegisterComponent<Rigidbody2DComponent>("GlitchyEngine.RigidBody2D");
|
||||
}
|
||||
|
||||
[RegisterMethod]
|
||||
/*[RegisterMethod]
|
||||
private static void RegisterCalls()
|
||||
{
|
||||
// Generated at CompTime
|
||||
}
|
||||
}*/
|
||||
|
||||
private static void RegisterComponent<T>(StringView cSharpClassName = "") where T : struct, new
|
||||
{
|
||||
@@ -104,13 +104,10 @@ static class ScriptGlue
|
||||
}
|
||||
|
||||
[RegisterCall("Log::LogMessage_Impl")]
|
||||
static void Log(int32 logLevel, MonoString* message)
|
||||
[Export, LinkName("Log::LogMessage_Impl"), CallingConvention(.Cdecl)]
|
||||
static void Log(int32 logLevel, char8* message)
|
||||
{
|
||||
char8* utfMessage = Mono.mono_string_to_utf8(message);
|
||||
|
||||
Log.ClientLogger.Log((LogLevel)logLevel, StringView(utfMessage));
|
||||
|
||||
Mono.mono_free(utfMessage);
|
||||
Log.ClientLogger.Log((LogLevel)logLevel, StringView(message));
|
||||
}
|
||||
|
||||
#region Input
|
||||
|
||||
Reference in New Issue
Block a user