Added EngineInterface

This commit is contained in:
Kah Wei 2022-09-13 11:43:49 +08:00
parent ccdb1d0e19
commit 4ed417cbea
9 changed files with 308 additions and 7 deletions

View File

@ -115,7 +115,7 @@ namespace SHADE
( (
runtimePath.c_str(), // AppDomain base path runtimePath.c_str(), // AppDomain base path
"SHADEHost", // AppDomain friendly name "SHADEHost", // AppDomain friendly name
propertyKeys.size(), // Property count static_cast<int>(propertyKeys.size()), // Property count
propertyKeys.data(), // Property names propertyKeys.data(), // Property names
propertyValues.data(), // Property values propertyValues.data(), // Property values
&hostHandle, // Host handle &hostHandle, // Host handle

View File

@ -244,10 +244,10 @@ namespace SHADE
<DebugSymbols>true</DebugSymbols>\n\ <DebugSymbols>true</DebugSymbols>\n\
</PropertyGroup>\n\ </PropertyGroup>\n\
<ItemGroup>\n\ <ItemGroup>\n\
<Compile Remove=\"bin\**\" />\n\ <Compile Remove=\"bin\\**\" />\n\
<EmbeddedResource Remove=\"Assets\**\" />\n\ <EmbeddedResource Remove=\"Assets\\**\" />\n\
<EmbeddedResource Remove=\"bin\**\" />\n\ <EmbeddedResource Remove=\"bin\\**\" />\n\
<None Remove=\"bin\**\" />\n\ <None Remove=\"bin\\**\" />\n\
</ItemGroup>\n\ </ItemGroup>\n\
<ItemGroup>\n\ <ItemGroup>\n\
<None Remove=\".gitignore\" />\n\ <None Remove=\".gitignore\" />\n\

View File

@ -183,8 +183,8 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constants */ /* Constants */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
static constexpr std::string_view DEFAULT_CSHARP_LIB_NAME = "SHADEAPI"; static constexpr std::string_view DEFAULT_CSHARP_LIB_NAME = "SHADE_Managed";
static constexpr std::string_view MANAGED_SCRIPT_LIB_NAME = "SHADEManaged"; static constexpr std::string_view MANAGED_SCRIPT_LIB_NAME = "SHADE_Scripting";
static const std::string DEFAULT_CSHARP_NAMESPACE; static const std::string DEFAULT_CSHARP_NAMESPACE;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -15,6 +15,9 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\Engine\EngineInterface.hxx">
<Filter>Engine</Filter>
</ClInclude>
<ClInclude Include="src\Engine\Entity.hxx"> <ClInclude Include="src\Engine\Entity.hxx">
<Filter>Engine</Filter> <Filter>Engine</Filter>
</ClInclude> </ClInclude>
@ -48,6 +51,10 @@
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\AssemblyInfo.cxx" />
<ClCompile Include="src\Engine\EngineInterface.cxx">
<Filter>Engine</Filter>
</ClCompile>
<ClCompile Include="src\Engine\Entity.cxx"> <ClCompile Include="src\Engine\Entity.cxx">
<Filter>Engine</Filter> <Filter>Engine</Filter>
</ClCompile> </ClCompile>

View File

@ -0,0 +1,39 @@
/************************************************************************************//*!
\file AssemblyInfo.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 24, 2021
\brief Defines the properties of this managed .NET Assembly.
Note: This file is written in C++17/CLI.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#include "SHpch.h"
/*-------------------------------------------------------------------------------------*/
/* Using Declarations */
/*-------------------------------------------------------------------------------------*/
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
/*-------------------------------------------------------------------------------------*/
/* Assembly Properties */
/*-------------------------------------------------------------------------------------*/
[assembly:AssemblyTitleAttribute(L"SHADE_Managed")];
[assembly:AssemblyDescriptionAttribute(L"")];
[assembly:AssemblyConfigurationAttribute(L"")];
[assembly:AssemblyCompanyAttribute(L"")];
[assembly:AssemblyProductAttribute(L"SHADE_Managed")];
[assembly:AssemblyCopyrightAttribute(L"Copyright (C) 2022 DigiPen Institute of Technology")];
[assembly:AssemblyTrademarkAttribute(L"")];
[assembly:AssemblyCultureAttribute(L"")];
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];

View File

@ -0,0 +1,138 @@
/************************************************************************************//*!
\file EngineInterface.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 28, 2021
\brief Contains the implementation of the managed EngineInterface static class.
Note: This file is written in C++17/CLI.
Copyright (C) 2021 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
// Precompiled Headers
#include "SHpch.h"
// Primary Header
#include "EngineInterface.hxx"
// Standard Libraries
#include <sstream>
// Project Headers
#include "Utility/Convert.hxx"
#include "Utility/Debug.hxx"
#include "Scripts/ScriptStore.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructor */
/*---------------------------------------------------------------------------------*/
static EngineInterface::EngineInterface()
{
exceptionHandler = gcnew System::UnhandledExceptionEventHandler(unhandledExceptionHandler);
managedLibPath = System::Reflection::Assembly::GetExecutingAssembly()->Location->Replace("SHADE_Managed.dll", ManagedLibraryName + ".dll");
}
/*---------------------------------------------------------------------------------*/
/* Interop Static Functions */
/*---------------------------------------------------------------------------------*/
void EngineInterface::Init()
{
SAFE_NATIVE_CALL_BEGIN
// Set up exception handler
System::AppDomain::CurrentDomain->UnhandledException += exceptionHandler;
LoadScriptAssembly();
Debug::Log("[EngineInterface] Successfully initialized managed runtime.");
SAFE_NATIVE_CALL_END_N("SHADE_Managed.EngineInterface")
}
void EngineInterface::UnloadScriptAssembly()
{
SAFE_NATIVE_CALL_BEGIN
std::ostringstream oss;
oss << "[EngineInterface] Unloading " << Convert::ToNative(ManagedLibraryName) << ".dll";
ScriptStore::Exit();
// Unload the script
scriptContext->Unload();
scriptContext = nullptr;
System::GC::Collect();
System::GC::WaitForPendingFinalizers();
// Unload the assembly File
if (managedLibFile != nullptr)
{
managedLibFile->Close();
managedLibFile = nullptr;
}
oss.str("");
oss << "[EngineInterface] Successfully unloaded " << Convert::ToNative(ManagedLibraryName) << ".dll";
Debug::Log(oss.str());
SAFE_NATIVE_CALL_END_N("SHADE_Managed.EngineInterface")
}
void EngineInterface::LoadScriptAssembly()
{
SAFE_NATIVE_CALL_BEGIN
scriptContext = gcnew DisposableAssemblyLoadContext();
loadManagedLibrary();
ScriptStore::Init();
SAFE_NATIVE_CALL_END_N("SHADE_Managed.EngineInterface")
}
void EngineInterface::ReloadScriptAssembly()
{
SAFE_NATIVE_CALL_BEGIN
// Stop scripts
UnloadScriptAssembly();
// Reload assembly and restart scripts runtime
LoadScriptAssembly();
SAFE_NATIVE_CALL_END_N("SHADE_Managed.EngineInterface")
}
void EngineInterface::Exit()
{
SAFE_NATIVE_CALL_BEGIN
// Clean up ScriptStore
ScriptStore::Exit();
scriptContext->Unload();
// Release exception handler
System::AppDomain::CurrentDomain->UnhandledException -= exceptionHandler;
SAFE_NATIVE_CALL_END_N("SHADE_Managed.EngineInterface")
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
void EngineInterface::loadManagedLibrary()
{
using namespace System::IO;
std::ostringstream oss;
try
{
oss << "[EngineInterface] Loading " << Convert::ToNative(ManagedLibraryName) << ".dll";
managedLibFile = File::Open(managedLibPath, FileMode::Open, FileAccess::Read);
scriptContext->LoadFromStream(managedLibFile);
oss.str("");
oss << "[EngineInterface] Successfully loaded " << Convert::ToNative(ManagedLibraryName) << ".dll";
Debug::Log(oss.str());
}
catch (System::Exception^ e)
{
oss << "[EngineInterface] Unable to load " << Convert::ToNative(ManagedLibraryName) << ".dll!"
<< "(" << Convert::ToNative(e->ToString()) << ")";
Debug::LogError(oss.str());
}
}
/*---------------------------------------------------------------------------------*/
/* Exception Handler Functions */
/*---------------------------------------------------------------------------------*/
void EngineInterface::unhandledExceptionHandler(System::Object^ sender, System::UnhandledExceptionEventArgs^ e)
{
std::ostringstream oss;
oss << "[EngineInterface] Unhandled managed exception: "
<< Convert::ToNative(e->ExceptionObject->GetType()->ToString()) << ": "
<< Convert::ToNative(e->ExceptionObject->ToString());
Debug::LogError(oss.str());
}
}

View File

@ -0,0 +1,90 @@
/************************************************************************************//*!
\file EngineInterface.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 28, 2021
\brief Contains the definitions of the managed EngineInterface static class.
Note: This file is written in C++17/CLI.
Copyright (C) 2021 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// Project Includes
#include "Utility/DisposableAssemblyLoadContext.hxx"
namespace SHADE
{
/// <summary>
/// Static class that contains the functions for interfacing with the core
/// PlushieEngine written in C++ for managing the lifecycle of managed code.
/// </summary>
private ref class EngineInterface abstract sealed
{
public:
/*-----------------------------------------------------------------------------*/
/* Constants */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Name of the Managed Library that contains the C# scripts written externally.
/// </summary>
literal System::String^ ManagedLibraryName = "SHADE_Scripting";
/*-----------------------------------------------------------------------------*/
/* Constructor */
/*-----------------------------------------------------------------------------*/
static EngineInterface();
/*-----------------------------------------------------------------------------*/
/* Interop Static Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Initialises all required components for managed code.
/// </summary>
static void Init();
/// <summary>
/// Unloads the managed script assembly.
/// Take note that this will clear all existing scripts, ensure that the scene
/// is saved before doing so.
/// </summary>
static void UnloadScriptAssembly();
/// <summary>
/// Loads the managed script assembly. Ensure this is only called after
/// UnloadScriptAssembly() has been called.
/// </summary>
static void LoadScriptAssembly();
/// <summary>
/// Reloads the managed script assembly.
/// Take note that this will clear all existing scripts, ensure that the scene
/// is saved before doing so.
/// Equivalent to calling UnloadScriptAssembly() and then LoadScriptAssembly().
/// </summary>
static void ReloadScriptAssembly();
/// <summary>
/// Cleans up all required components for managed code.
/// </summary>
static void Exit();
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
static DisposableAssemblyLoadContext^ scriptContext;
static System::UnhandledExceptionEventHandler^ exceptionHandler;
static System::String^ managedLibPath;
static System::IO::FileStream^ managedLibFile;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
static void loadManagedLibrary();
/*-----------------------------------------------------------------------------*/
/* Exception Handler Functions */
/*-----------------------------------------------------------------------------*/
static void unhandledExceptionHandler(System::Object^ sender, System::UnhandledExceptionEventArgs^ e);
};
}

View File

@ -28,6 +28,10 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Logging Functions */ /* Logging Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void Debug::Log(const std::string& str)
{
SHLOG_INFO(str);
}
void Debug::Log(System::String^ str) void Debug::Log(System::String^ str)
{ {
SHLOG_INFO(Convert::ToNative(str)); SHLOG_INFO(Convert::ToNative(str));
@ -47,6 +51,10 @@ namespace SHADE
oss << "[" << throwerName << "] " << Convert::ToNative(str); oss << "[" << throwerName << "] " << Convert::ToNative(str);
SHLOG_INFO(oss.str()); SHLOG_INFO(oss.str());
} }
void Debug::LogWarning(const std::string& str)
{
SHLOG_WARNING(str);
}
void Debug::LogWarning(System::String^ str) void Debug::LogWarning(System::String^ str)
{ {
SHLOG_WARNING(Convert::ToNative(str)); SHLOG_WARNING(Convert::ToNative(str));
@ -66,6 +74,10 @@ namespace SHADE
oss << "[" << throwerName << "] " << Convert::ToNative(str); oss << "[" << throwerName << "] " << Convert::ToNative(str);
SHLOG_WARNING(oss.str()); SHLOG_WARNING(oss.str());
} }
void Debug::LogError(const std::string& str)
{
SHLOG_ERROR(str);
}
void Debug::LogError(System::String^ str) void Debug::LogError(System::String^ str)
{ {
SHLOG_ERROR(Convert::ToNative(str)); SHLOG_ERROR(Convert::ToNative(str));

View File

@ -98,6 +98,11 @@ namespace SHADE
/// Logs a message to the output. /// Logs a message to the output.
/// </summary> /// </summary>
/// <param name="str">The string to output.</param> /// <param name="str">The string to output.</param>
static void Log(const std::string& str);
/// <summary>
/// Logs a message to the output.
/// </summary>
/// <param name="str">The string to output.</param>
static void Log(System::String^ str); static void Log(System::String^ str);
/// <summary> /// <summary>
/// Logs a message to the output with a label such that it looks like this: /// Logs a message to the output with a label such that it looks like this:
@ -133,6 +138,11 @@ namespace SHADE
/// Logs a warning message to the output. /// Logs a warning message to the output.
/// </summary> /// </summary>
/// <param name="str">The string to output.</param> /// <param name="str">The string to output.</param>
static void LogWarning(const std::string& str);
/// <summary>
/// Logs a warning message to the output.
/// </summary>
/// <param name="str">The string to output.</param>
static void LogWarning(System::String^ str); static void LogWarning(System::String^ str);
/// <summary> /// <summary>
/// Logs a warning message to the output with a label such that it looks like this: /// Logs a warning message to the output with a label such that it looks like this:
@ -168,6 +178,11 @@ namespace SHADE
/// Logs a error message to the output. /// Logs a error message to the output.
/// </summary> /// </summary>
/// <param name="str">The string to output.</param> /// <param name="str">The string to output.</param>
static void LogError(const std::string& str);
/// <summary>
/// Logs a error message to the output.
/// </summary>
/// <param name="str">The string to output.</param>
static void LogError(System::String^ str); static void LogError(System::String^ str);
/// <summary> /// <summary>
/// Logs a error message to the output with a label such that it looks like this: /// Logs a error message to the output with a label such that it looks like this: