From 8938f13a0b701d6b7aacb20928a15db1c19dcfa7 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 23 Oct 2021 16:41:57 +0200 Subject: [PATCH] Add support for compiling and running engine without C# scripting (configurable via `EngineConfiguration.UseCSharp` in Flax.Build) --- Source/Editor/Cooker/GameCooker.cpp | 5 +- .../Editor/CustomEditors/CustomEditorsUtil.h | 2 + Source/Editor/Managed/ManagedEditor.cpp | 8 +- Source/Editor/Scripting/ScriptsBuilder.cpp | 2 +- .../Animations/Graph/AnimGraph.Custom.cpp | 18 +- .../SceneAnimations/SceneAnimationPlayer.cpp | 28 +- .../SceneAnimations/SceneAnimationPlayer.h | 2 +- Source/Engine/Content/Asset.cpp | 4 + Source/Engine/Content/AssetReference.h | 2 +- Source/Engine/Content/Assets/VisualScript.cpp | 9 + Source/Engine/Content/WeakAssetReference.h | 2 +- Source/Engine/Core/Types/Variant.cpp | 54 +++- Source/Engine/Debug/DebugLog.cpp | 25 +- Source/Engine/Debug/DebugLog.h | 2 +- Source/Engine/Engine/Engine.cpp | 4 +- Source/Engine/Graphics/Models/Mesh.cpp | 10 + Source/Engine/Graphics/Models/Mesh.h | 2 + Source/Engine/Graphics/Models/SkinnedMesh.cpp | 6 + Source/Engine/Graphics/Models/SkinnedMesh.h | 2 + Source/Engine/Graphics/RenderTask.cpp | 21 +- Source/Engine/Level/Actors/Spline.cpp | 6 + Source/Engine/Level/Actors/Spline.h | 2 + Source/Engine/Level/SceneObject.cpp | 4 + Source/Engine/Localization/CultureInfo.cpp | 6 - Source/Engine/Platform/Base/WindowBase.cpp | 15 +- Source/Engine/Scripting/BinaryModule.cpp | 42 ++- Source/Engine/Scripting/BinaryModule.h | 4 + Source/Engine/Scripting/InternalCalls.h | 13 + .../InternalCalls/EngineInternalCalls.cpp | 6 + .../Scripting/InternalCalls/ManagedBitArray.h | 5 +- .../InternalCalls/ManagedDictionary.h | 7 +- Source/Engine/Scripting/MException.cpp | 6 +- Source/Engine/Scripting/MException.h | 4 +- .../MainThreadManagedInvokeAction.cpp | 13 +- .../Scripting/MainThreadManagedInvokeAction.h | 14 +- .../{MAssembly.Mono.cpp => MAssembly.cpp} | 48 ++-- .../Engine/Scripting/ManagedCLR/MAssembly.h | 30 +- .../{MClass.Mono.cpp => MClass.cpp} | 143 ++++++---- Source/Engine/Scripting/ManagedCLR/MClass.h | 33 +-- .../ManagedCLR/{MCore.Mono.cpp => MCore.cpp} | 111 +++++--- Source/Engine/Scripting/ManagedCLR/MCore.h | 48 +--- .../{MDomain.Mono.cpp => MDomain.cpp} | 33 +-- Source/Engine/Scripting/ManagedCLR/MDomain.h | 43 ++- .../{MEvent.Mono.cpp => MEvent.cpp} | 34 ++- Source/Engine/Scripting/ManagedCLR/MEvent.h | 18 +- .../{MField.Mono.cpp => MField.cpp} | 46 +++- Source/Engine/Scripting/ManagedCLR/MField.h | 29 +- .../{MMethod.Mono.cpp => MMethod.cpp} | 54 +++- Source/Engine/Scripting/ManagedCLR/MMethod.h | 24 +- .../{MProperty.Mono.cpp => MProperty.cpp} | 48 ++-- .../Engine/Scripting/ManagedCLR/MProperty.h | 24 +- .../Scripting/ManagedCLR/MStaticConverter.h | 4 + Source/Engine/Scripting/ManagedCLR/MType.cpp | 9 +- Source/Engine/Scripting/ManagedCLR/MType.h | 7 +- Source/Engine/Scripting/ManagedCLR/MTypes.h | 52 +--- Source/Engine/Scripting/ManagedCLR/MUtils.cpp | 4 + Source/Engine/Scripting/ManagedCLR/MUtils.h | 5 + .../Engine/Scripting/ManagedSerialization.cpp | 9 +- .../Engine/Scripting/ManagedSerialization.h | 2 + .../Scripting/Plugins/PluginManager.cpp | 12 +- Source/Engine/Scripting/Scripting.Build.cs | 6 +- .../Engine/Scripting/Scripting.Internal.cpp | 10 + Source/Engine/Scripting/Scripting.cpp | 102 ++++--- Source/Engine/Scripting/Scripting.h | 24 +- Source/Engine/Scripting/ScriptingCalls.h | 20 +- Source/Engine/Scripting/ScriptingObject.cpp | 54 +++- Source/Engine/Scripting/ScriptingObject.h | 15 +- .../Scripting/ScriptingObjectReference.h | 4 +- Source/Engine/Scripting/ScriptingType.h | 7 +- Source/Engine/Scripting/SoftObjectReference.h | 4 +- Source/Engine/Scripting/StdTypesContainer.cpp | 2 + Source/Engine/Scripting/Types.h | 55 ++++ Source/Engine/Serialization/Serialization.cpp | 4 + Source/Engine/Serialization/Stream.cpp | 4 + Source/Engine/Threading/JobSystem.cpp | 2 +- Source/Engine/UI/UICanvas.cpp | 18 +- Source/Engine/UI/UIControl.cpp | 18 +- Source/Engine/Visject/VisjectGraph.cpp | 4 + .../Bindings/BindingsGenerator.Cpp.cs | 256 +++++++++++------- .../Flax.Build/Bindings/BindingsGenerator.cs | 33 ++- .../Flax.Build/Build/DotNet/Builder.DotNet.cs | 2 +- .../Build/NativeCpp/Builder.NativeCpp.cs | 33 ++- .../Build/Plugins/VisualScriptingPlugin.cs | 6 +- .../Tools/Flax.Build/Build/ProjectTarget.cs | 6 + Source/Tools/Flax.Build/Configuration.cs | 17 ++ Source/Tools/Flax.Build/Program.cs | 1 + 86 files changed, 1244 insertions(+), 688 deletions(-) rename Source/Engine/Scripting/ManagedCLR/{MAssembly.Mono.cpp => MAssembly.cpp} (98%) rename Source/Engine/Scripting/ManagedCLR/{MClass.Mono.cpp => MClass.cpp} (84%) rename Source/Engine/Scripting/ManagedCLR/{MCore.Mono.cpp => MCore.cpp} (98%) rename Source/Engine/Scripting/ManagedCLR/{MDomain.Mono.cpp => MDomain.cpp} (82%) rename Source/Engine/Scripting/ManagedCLR/{MEvent.Mono.cpp => MEvent.cpp} (91%) rename Source/Engine/Scripting/ManagedCLR/{MField.Mono.cpp => MField.cpp} (86%) rename Source/Engine/Scripting/ManagedCLR/{MMethod.Mono.cpp => MMethod.cpp} (88%) rename Source/Engine/Scripting/ManagedCLR/{MProperty.Mono.cpp => MProperty.cpp} (89%) diff --git a/Source/Editor/Cooker/GameCooker.cpp b/Source/Editor/Cooker/GameCooker.cpp index 9ff5445a7..452f4d230 100644 --- a/Source/Editor/Cooker/GameCooker.cpp +++ b/Source/Editor/Cooker/GameCooker.cpp @@ -3,6 +3,7 @@ #include "GameCooker.h" #include "FlaxEngine.Gen.h" #include "Engine/Scripting/MainThreadManagedInvokeAction.h" +#include "Engine/Scripting/ManagedCLR/MTypes.h" #include "Engine/Scripting/ManagedCLR/MClass.h" #include "Engine/Scripting/Scripting.h" #include "Engine/Scripting/ScriptingType.h" @@ -450,7 +451,7 @@ void GameCookerImpl::OnCollectAssets(HashSet& assets) } MCore::AttachThread(); - MonoObject* exception = nullptr; + MObject* exception = nullptr; auto list = (MonoArray*)Internal_OnCollectAssets->Invoke(nullptr, nullptr, &exception); if (exception) { @@ -486,7 +487,7 @@ bool GameCookerImpl::Build() Steps.Add(New()); } - MCore::Instance()->AttachThread(); + MCore::AttachThread(); // Build Started CallEvent(GameCooker::EventType::BuildStarted); diff --git a/Source/Editor/CustomEditors/CustomEditorsUtil.h b/Source/Editor/CustomEditors/CustomEditorsUtil.h index 55f5011e8..37c883882 100644 --- a/Source/Editor/CustomEditors/CustomEditorsUtil.h +++ b/Source/Editor/CustomEditors/CustomEditorsUtil.h @@ -11,5 +11,7 @@ class CustomEditorsUtil { public: +#if USE_MONO static MonoReflectionType* GetCustomEditor(MonoReflectionType* refType); +#endif }; diff --git a/Source/Editor/Managed/ManagedEditor.cpp b/Source/Editor/Managed/ManagedEditor.cpp index 089faeb7f..4ac4709a3 100644 --- a/Source/Editor/Managed/ManagedEditor.cpp +++ b/Source/Editor/Managed/ManagedEditor.cpp @@ -126,7 +126,7 @@ void OnVisualScriptingDebugFlow() flowInfo.ScriptInstance = stack->Instance ? stack->Instance->GetOrCreateManagedInstance() : nullptr; flowInfo.NodeId = stack->Node->ID; flowInfo.BoxId = stack->Box->ID; - MonoObject* exception = nullptr; + MObject* exception = nullptr; void* params[1]; params[0] = &flowInfo; Internal_OnVisualScriptingDebugFlow->Invoke(nullptr, params, &exception); @@ -191,7 +191,7 @@ void ManagedEditor::Init() { LOG(Fatal, "Failed to create editor instance."); } - MonoObject* exception = nullptr; + MObject* exception = nullptr; bool isHeadless = CommandLine::Options.Headless.IsTrue(); bool skipCompile = CommandLine::Options.SkipCompile.IsTrue(); bool newProject = CommandLine::Options.NewProject.IsTrue(); @@ -259,7 +259,7 @@ void ManagedEditor::Update() } // Call update - MonoObject* exception = nullptr; + MObject* exception = nullptr; UpdateMethod->Invoke(instance, nullptr, &exception); if (exception) { @@ -291,7 +291,7 @@ void ManagedEditor::Exit() { LOG(Fatal, "Invalid Editor assembly!"); } - MonoObject* exception = nullptr; + MObject* exception = nullptr; exitMethod->Invoke(instance, nullptr, &exception); if (exception) { diff --git a/Source/Editor/Scripting/ScriptsBuilder.cpp b/Source/Editor/Scripting/ScriptsBuilder.cpp index 3c9ee4315..c8e9d4cef 100644 --- a/Source/Editor/Scripting/ScriptsBuilder.cpp +++ b/Source/Editor/Scripting/ScriptsBuilder.cpp @@ -456,7 +456,7 @@ void ScriptsBuilderImpl::CallCompileEvent(EventData& data) LOG(Fatal, "Invalid Editor assembly!"); } } - /*MonoObject* exception = nullptr; + /*MObject* exception = nullptr; void* args[1]; args[0] = &data.Type; Internal_OnEvent->Invoke(nullptr, args, &exception); diff --git a/Source/Engine/Animations/Graph/AnimGraph.Custom.cpp b/Source/Engine/Animations/Graph/AnimGraph.Custom.cpp index 5c082a8b5..3958f5d48 100644 --- a/Source/Engine/Animations/Graph/AnimGraph.Custom.cpp +++ b/Source/Engine/Animations/Graph/AnimGraph.Custom.cpp @@ -11,6 +11,9 @@ #include "Engine/Scripting/Scripting.h" #include "Engine/Scripting/MException.h" #include "Engine/Content/Assets/SkinnedModel.h" + +#if USE_MONO + #include struct InternalInitData @@ -80,15 +83,20 @@ namespace AnimGraphInternal } } +#endif + void AnimGraphExecutor::initRuntime() { +#if USE_MONO ADD_INTERNAL_CALL("FlaxEngine.AnimationGraph::Internal_HasConnection", &AnimGraphInternal::HasConnection); ADD_INTERNAL_CALL("FlaxEngine.AnimationGraph::Internal_GetInputValue", &AnimGraphInternal::GetInputValue); ADD_INTERNAL_CALL("FlaxEngine.AnimationGraph::Internal_GetOutputImpulseData", &AnimGraphInternal::GetOutputImpulseData); +#endif } void AnimGraphExecutor::ProcessGroupCustom(Box* boxBase, Node* nodeBase, Value& value) { +#if USE_MONO auto& context = Context.Get(); if (context.ValueCache.TryGet(boxBase, value)) return; @@ -124,7 +132,7 @@ void AnimGraphExecutor::ProcessGroupCustom(Box* boxBase, Node* nodeBase, Value& // Evaluate node void* params[1]; params[0] = &internalContext; - MonoObject* exception = nullptr; + MObject* exception = nullptr; MonoObject* result = data.Evaluate->Invoke(obj, params, &exception); if (exception) { @@ -136,6 +144,7 @@ void AnimGraphExecutor::ProcessGroupCustom(Box* boxBase, Node* nodeBase, Value& // Extract result value = MUtils::UnboxVariant(result); context.ValueCache.Add(boxBase, value); +#endif } bool AnimGraph::IsReady() const @@ -156,13 +165,16 @@ void AnimGraph::ClearCustomNode(Node* node) data.Evaluate = nullptr; if (data.Handle) { +#if USE_MONO mono_gchandle_free(data.Handle); +#endif data.Handle = 0; } } bool AnimGraph::InitCustomNode(Node* node) { +#if USE_MONO // Fetch the node logic controller type if (node->Values.Count() < 2 || node->Values[0].Type.Type != ValueType::String) { @@ -212,7 +224,7 @@ bool AnimGraph::InitCustomNode(Node* node) initData.BaseModel = BaseModel.GetManagedInstance(); void* params[1]; params[0] = &initData; - MonoObject* exception = nullptr; + MObject* exception = nullptr; load->Invoke(obj, params, &exception); if (exception) { @@ -227,7 +239,7 @@ bool AnimGraph::InitCustomNode(Node* node) auto& data = node->Data.Custom; data.Evaluate = evaluate; data.Handle = handleGC; - +#endif return false; } diff --git a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.cpp b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.cpp index 5ed3e7057..7f9a4eead 100644 --- a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.cpp +++ b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.cpp @@ -260,6 +260,7 @@ void SceneAnimationPlayer::MapTrack(const StringView& from, const Guid& to) void SceneAnimationPlayer::Restore(SceneAnimation* anim, int32 stateIndexOffset) { +#if USE_MONO // Restore all tracks for (int32 j = 0; j < anim->Tracks.Count(); j++) { @@ -293,7 +294,7 @@ void SceneAnimationPlayer::Restore(SceneAnimation* anim, int32 stateIndexOffset) || state.RestoreStateIndex == -1 || (state.Field == nullptr && state.Property == nullptr)) break; - MonoObject* instance = _tracks[stateIndexOffset + parentTrack.TrackStateIndex].ManagedObject; + MObject* instance = _tracks[stateIndexOffset + parentTrack.TrackStateIndex].ManagedObject; if (!instance) break; @@ -318,7 +319,7 @@ void SceneAnimationPlayer::Restore(SceneAnimation* anim, int32 stateIndexOffset) { if (state.Property) { - MonoObject* exception = nullptr; + MObject* exception = nullptr; state.ManagedObject = state.Property->GetValue(instance, &exception); if (exception) { @@ -341,7 +342,7 @@ void SceneAnimationPlayer::Restore(SceneAnimation* anim, int32 stateIndexOffset) // Set the value if (state.Property) { - MonoObject* exception = nullptr; + MObject* exception = nullptr; state.Property->SetValue(instance, value, &exception); if (exception) { @@ -353,16 +354,17 @@ void SceneAnimationPlayer::Restore(SceneAnimation* anim, int32 stateIndexOffset) { state.Field->SetValue(instance, value); } - break; } default: ; } } +#endif } bool SceneAnimationPlayer::TickPropertyTrack(int32 trackIndex, int32 stateIndexOffset, SceneAnimation* anim, float time, const SceneAnimation::Track& track, TrackInstance& state, void* target) { +#if USE_MONO switch (track.Type) { case SceneAnimation::Track::Types::KeyframesProperty: @@ -511,17 +513,18 @@ bool SceneAnimationPlayer::TickPropertyTrack(int32 trackIndex, int32 stateIndexO case SceneAnimation::Track::Types::ObjectProperty: { // Cache the sub-object pointer for the sub-tracks - state.ManagedObject = *(MonoObject**)target; + state.ManagedObject = *(MObject**)target; return false; } default: ; } - +#endif return true; } void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int32 stateIndexOffset, CallStack& callStack) { +#if USE_MONO const float fps = anim->FramesPerSecond; #if !BUILD_RELEASE || USE_EDITOR callStack.Add(anim); @@ -827,7 +830,7 @@ void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int3 break; // Skip if parent object is missing - MonoObject* instance = _tracks[stateIndexOffset + parentTrack.TrackStateIndex].ManagedObject; + MObject* instance = _tracks[stateIndexOffset + parentTrack.TrackStateIndex].ManagedObject; if (!instance) break; @@ -860,7 +863,7 @@ void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int3 { if (state.Property) { - MonoObject* exception = nullptr; + MObject* exception = nullptr; auto boxed = state.Property->GetValue(instance, &exception); if (exception) { @@ -876,7 +879,7 @@ void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int3 } else { - *(MonoObject**)value = boxed; + *(MObject**)value = boxed; } } else @@ -900,7 +903,7 @@ void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int3 } case SceneAnimation::Track::Types::ObjectReferenceProperty: { - auto obj = Scripting::FindObject(*(MonoObject**)value); + auto obj = Scripting::FindObject(*(MObject**)value); auto id = obj ? obj->GetID() : Guid::Empty; _restoreData.Add((byte*)&id, sizeof(Guid)); break; @@ -922,7 +925,7 @@ void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int3 value = (void*)*(intptr*)value; if (state.Property) { - MonoObject* exception = nullptr; + MObject* exception = nullptr; state.Property->SetValue(instance, value, &exception); if (exception) { @@ -995,7 +998,7 @@ void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int3 // Invoke the method Variant result; - MonoObject* exception = nullptr; + MObject* exception = nullptr; mono_runtime_invoke((MonoMethod*)state.Method, instance, paramsData, &exception); if (exception) { @@ -1064,6 +1067,7 @@ void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int3 default: ; } } +#endif } void SceneAnimationPlayer::Tick() diff --git a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h index 5d7d4737b..6d38e743f 100644 --- a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h +++ b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h @@ -43,7 +43,7 @@ private: struct TrackInstance { ScriptingObjectReference Object; - MonoObject* ManagedObject = nullptr; + MObject* ManagedObject = nullptr; MProperty* Property = nullptr; MField* Field = nullptr; void* Method = nullptr; diff --git a/Source/Engine/Content/Asset.cpp b/Source/Engine/Content/Asset.cpp index 45dd1c626..7e994270f 100644 --- a/Source/Engine/Content/Asset.cpp +++ b/Source/Engine/Content/Asset.cpp @@ -11,7 +11,9 @@ #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Threading/MainThreadTask.h" #include "Engine/Threading/ConcurrentTaskQueue.h" +#if USE_MONO #include +#endif AssetReferenceBase::~AssetReferenceBase() { @@ -202,7 +204,9 @@ void Asset::OnManagedInstanceDeleted() // Cleanup if (_gcHandle) { +#if USE_MONO mono_gchandle_free(_gcHandle); +#endif _gcHandle = 0; } diff --git a/Source/Engine/Content/AssetReference.h b/Source/Engine/Content/AssetReference.h index 90f472fd6..d6bf09222 100644 --- a/Source/Engine/Content/AssetReference.h +++ b/Source/Engine/Content/AssetReference.h @@ -60,7 +60,7 @@ public: /// /// Gets managed instance object (or null if no asset set). /// - FORCE_INLINE MonoObject* GetManagedInstance() const + FORCE_INLINE MObject* GetManagedInstance() const { return _asset ? _asset->GetOrCreateManagedInstance() : nullptr; } diff --git a/Source/Engine/Content/Assets/VisualScript.cpp b/Source/Engine/Content/Assets/VisualScript.cpp index 8649a3dd1..3cd379d79 100644 --- a/Source/Engine/Content/Assets/VisualScript.cpp +++ b/Source/Engine/Content/Assets/VisualScript.cpp @@ -310,10 +310,17 @@ void VisualScriptExecutor::ProcessGroupTools(Box* box, Node* node, Value& value) const StringAsANSI<100> typeNameAnsi(typeName.Get(), typeName.Length()); if (StringUtils::Compare(typeNameAnsi.Get(), obj.Type.GetTypeName()) != 0) { +#if USE_MONO MonoClass* klass = Scripting::FindClassNative(StringAnsiView(typeNameAnsi.Get(), typeName.Length())); MonoClass* objKlass = MUtils::GetClass(obj); if (!klass || !objKlass || mono_class_is_subclass_of(objKlass, klass, false) == 0) obj = Value::Null; +#else + const ScriptingTypeHandle type = Scripting::FindScriptingType(StringAnsiView(typeNameAnsi.Get(), typeName.Length())); + const ScriptingTypeHandle objType = Scripting::FindScriptingType(obj.Type.GetTypeName()); + if (!type || !objType || objType.IsSubclassOf(type)) + obj = Value::Null; +#endif } } @@ -448,6 +455,7 @@ void VisualScriptExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value& } else { +#if !COMPILE_WITHOUT_CSHARP // Fallback to C#-only types const auto mclass = Scripting::FindClass(StringAnsiView(typeNameAnsi.Get(), typeName.Length())); if (mclass) @@ -461,6 +469,7 @@ void VisualScriptExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value& } } else +#endif { if (typeName.HasChars()) { diff --git a/Source/Engine/Content/WeakAssetReference.h b/Source/Engine/Content/WeakAssetReference.h index 678e2b998..a39623b93 100644 --- a/Source/Engine/Content/WeakAssetReference.h +++ b/Source/Engine/Content/WeakAssetReference.h @@ -50,7 +50,7 @@ public: /// /// Gets managed instance object (or null if no asset set). /// - FORCE_INLINE MonoObject* GetManagedInstance() const + FORCE_INLINE MObject* GetManagedInstance() const { return _asset ? _asset->GetOrCreateManagedInstance() : nullptr; } diff --git a/Source/Engine/Core/Types/Variant.cpp b/Source/Engine/Core/Types/Variant.cpp index 683b195be..419be7a35 100644 --- a/Source/Engine/Core/Types/Variant.cpp +++ b/Source/Engine/Core/Types/Variant.cpp @@ -64,6 +64,7 @@ VariantType::VariantType(Types type, _MonoClass* klass) { Type = type; TypeName = nullptr; +#if USE_MONO if (klass) { MString typeName; @@ -72,6 +73,7 @@ VariantType::VariantType(Types type, _MonoClass* klass) TypeName = static_cast(Allocator::Allocate(length)); Platform::MemoryCopy(TypeName, typeName.Get(), length); } +#endif } VariantType::VariantType(const VariantType& other) @@ -517,12 +519,24 @@ Variant::Variant(Asset* v) } } +#if USE_MONO + Variant::Variant(_MonoObject* v) : Type(VariantType::ManagedObject, v ? mono_object_get_class(v) : nullptr) { AsUint = v ? mono_gchandle_new(v, true) : 0; } +#else + +Variant::Variant(_MonoObject* v) + : Type(VariantType::ManagedObject, nullptr) +{ + AsUint = 0; +} + +#endif + Variant::Variant(const StringView& v) : Type(VariantType::String) { @@ -788,8 +802,8 @@ Variant::~Variant() case VariantType::Dictionary: Delete(AsDictionary); break; -#if USE_MONO case VariantType::ManagedObject: +#if USE_MONO if (AsUint) mono_gchandle_free(AsUint); break; @@ -912,7 +926,9 @@ Variant& Variant::operator=(const Variant& other) AsDictionary = New>(*other.AsDictionary); break; case VariantType::ManagedObject: +#if USE_MONO AsUint = other.AsUint ? mono_gchandle_new(mono_gchandle_get_target(other.AsUint), true) : 0; +#endif break; case VariantType::Null: case VariantType::Void: @@ -1015,9 +1031,6 @@ bool Variant::operator==(const Variant& other) const return false; } return true; - case VariantType::ManagedObject: - // TODO: invoke C# Equality logic? - return AsUint == other.AsUint || mono_gchandle_get_target(AsUint) == mono_gchandle_get_target(other.AsUint); case VariantType::Typename: if (AsBlob.Data == nullptr && other.AsBlob.Data == nullptr) return true; @@ -1026,6 +1039,11 @@ bool Variant::operator==(const Variant& other) const if (other.AsBlob.Data == nullptr) return false; return AsBlob.Length == other.AsBlob.Length && StringUtils::Compare(static_cast(AsBlob.Data), static_cast(other.AsBlob.Data), AsBlob.Length - 1) == 0; + case VariantType::ManagedObject: +#if USE_MONO + // TODO: invoke C# Equality logic? + return AsUint == other.AsUint || mono_gchandle_get_target(AsUint) == mono_gchandle_get_target(other.AsUint); +#endif default: return false; } @@ -1115,7 +1133,9 @@ Variant::operator bool() const case VariantType::Asset: return AsAsset != nullptr; case VariantType::ManagedObject: +#if USE_MONO return AsUint != 0 && mono_gchandle_get_target(AsUint) != nullptr; +#endif default: return false; } @@ -1461,7 +1481,9 @@ Variant::operator void*() const case VariantType::Blob: return AsBlob.Data; case VariantType::ManagedObject: +#if USE_MONO return AsUint ? mono_gchandle_get_target(AsUint) : nullptr; +#endif default: return nullptr; } @@ -1504,7 +1526,11 @@ Variant::operator ScriptingObject*() const Variant::operator _MonoObject*() const { +#if USE_MONO return Type.Type == VariantType::ManagedObject && AsUint ? mono_gchandle_get_target(AsUint) : nullptr; +#else + return nullptr; +#endif } Variant::operator Asset*() const @@ -2011,8 +2037,10 @@ void Variant::SetType(const VariantType& type) Delete(AsDictionary); break; case VariantType::ManagedObject: +#if USE_MONO if (AsUint) mono_gchandle_free(AsUint); +#endif break; default: ; } @@ -2105,8 +2133,10 @@ void Variant::SetType(VariantType&& type) Delete(AsDictionary); break; case VariantType::ManagedObject: +#if USE_MONO if (AsUint) mono_gchandle_free(AsUint); +#endif break; default: ; } @@ -2245,6 +2275,7 @@ void Variant::SetObject(ScriptingObject* object) void Variant::SetManagedObject(_MonoObject* object) { +#if USE_MONO if (object) { if (Type.Type != VariantType::ManagedObject) @@ -2257,6 +2288,7 @@ void Variant::SetManagedObject(_MonoObject* object) SetType(VariantType(VariantType::ManagedObject)); AsUint = 0; } +#endif } void Variant::SetAsset(Asset* asset) @@ -2338,10 +2370,12 @@ String Variant::ToString() const return (*(Ray*)AsBlob.Data).ToString(); case VariantType::Matrix: return (*(Matrix*)AsBlob.Data).ToString(); - case VariantType::ManagedObject: - return AsUint ? String(MUtils::ToString(mono_object_to_string(mono_gchandle_get_target(AsUint), nullptr))) : TEXT("null"); case VariantType::Typename: return String((const char*)AsBlob.Data, AsBlob.Length ? AsBlob.Length - 1 : 0); + case VariantType::ManagedObject: +#if USE_MONO + return AsUint ? String(MUtils::ToString(mono_object_to_string(mono_gchandle_get_target(AsUint), nullptr))) : TEXT("null"); +#endif default: return String::Empty; } @@ -3110,6 +3144,7 @@ void Variant::AllocStructure() AsBlob.Data = Allocator::Allocate(AsBlob.Length); *((int16*)AsBlob.Data) = 0; } +#if USE_MONO else if (const auto mclass = Scripting::FindClass(typeName)) { // Fallback to C#-only types @@ -3134,6 +3169,7 @@ void Variant::AllocStructure() AsBlob.Length = 0; } } +#endif else { if (typeName.Length() != 0) @@ -3213,10 +3249,12 @@ uint32 GetHash(const Variant& key) return GetHash(*(Color*)key.AsData); case VariantType::Guid: return GetHash(*(Guid*)key.AsData); - case VariantType::ManagedObject: - return key.AsUint ? (uint32)mono_object_hash(mono_gchandle_get_target(key.AsUint)) : 0; case VariantType::Typename: return GetHash((const char*)key.AsBlob.Data); + case VariantType::ManagedObject: +#if USE_MONO + return key.AsUint ? (uint32)mono_object_hash(mono_gchandle_get_target(key.AsUint)) : 0; +#endif default: return 0; } diff --git a/Source/Engine/Debug/DebugLog.cpp b/Source/Engine/Debug/DebugLog.cpp index fb0ab901b..a7773fc4a 100644 --- a/Source/Engine/Debug/DebugLog.cpp +++ b/Source/Engine/Debug/DebugLog.cpp @@ -9,6 +9,9 @@ #include "Engine/Scripting/ManagedCLR/MClass.h" #include "Engine/Threading/Threading.h" #include "FlaxEngine.Gen.h" + +#if USE_MONO + #include #include @@ -61,8 +64,11 @@ bool CacheMethods() return false; } +#endif + void DebugLog::Log(LogType type, const StringView& message) { +#if USE_MONO if (CacheMethods()) return; @@ -77,34 +83,41 @@ void DebugLog::Log(LogType type, const StringView& message) params.AddParam(stackTrace, scriptsDomain->GetNative()); #endif MainThreadManagedInvokeAction::Invoke(Internal_SendLog, params); +#endif } -void DebugLog::LogException(MonoObject* exceptionObject) +void DebugLog::LogException(MObject* exceptionObject) { +#if USE_MONO if (exceptionObject == nullptr || CacheMethods()) return; MainThreadManagedInvokeAction::ParamsBuilder params; params.AddParam(exceptionObject); MainThreadManagedInvokeAction::Invoke(Internal_SendLogException, params); +#endif } String DebugLog::GetStackTrace() { String result; +#if USE_MONO if (!CacheMethods()) { auto stackTraceObj = Internal_GetStackTrace->Invoke(nullptr, nullptr, nullptr); MUtils::ToString((MonoString*)stackTraceObj, result); } +#endif return result; } void DebugLog::ThrowException(const char* msg) { +#if USE_MONO // Throw exception to the C# world auto ex = mono_exception_from_name_msg(mono_get_corlib(), "System", "Exception", msg); mono_raise_exception(ex); +#endif } void DebugLog::ThrowNullReference() @@ -112,35 +125,45 @@ void DebugLog::ThrowNullReference() //LOG(Warning, "Invalid null reference."); //LOG_STR(Warning, DebugLog::GetStackTrace()); +#if USE_MONO // Throw exception to the C# world auto ex = mono_get_exception_null_reference(); mono_raise_exception(ex); +#endif } void DebugLog::ThrowArgument(const char* arg, const char* msg) { +#if USE_MONO // Throw exception to the C# world auto ex = mono_get_exception_argument(arg, msg); mono_raise_exception(ex); +#endif } void DebugLog::ThrowArgumentNull(const char* arg) { +#if USE_MONO // Throw exception to the C# world auto ex = mono_get_exception_argument_null(arg); mono_raise_exception(ex); +#endif } void DebugLog::ThrowArgumentOutOfRange(const char* arg) { +#if USE_MONO // Throw exception to the C# world auto ex = mono_get_exception_argument_out_of_range(arg); mono_raise_exception(ex); +#endif } void DebugLog::ThrowNotSupported(const char* msg) { +#if USE_MONO // Throw exception to the C# world auto ex = mono_get_exception_not_supported(msg); mono_raise_exception(ex); +#endif } diff --git a/Source/Engine/Debug/DebugLog.h b/Source/Engine/Debug/DebugLog.h index 2fd210563..fe4fd2642 100644 --- a/Source/Engine/Debug/DebugLog.h +++ b/Source/Engine/Debug/DebugLog.h @@ -50,7 +50,7 @@ public: /// Logs a formatted exception message to the Flax Console. /// /// Runtime Exception. - static void LogException(MonoObject* exceptionObject); + static void LogException(MObject* exceptionObject); public: diff --git a/Source/Engine/Engine/Engine.cpp b/Source/Engine/Engine/Engine.cpp index 4831280ed..a50999d24 100644 --- a/Source/Engine/Engine/Engine.cpp +++ b/Source/Engine/Engine/Engine.cpp @@ -605,7 +605,7 @@ void EngineImpl::InitMainWindow() return; } -#if !USE_EDITOR +#if !USE_EDITOR && !COMPILE_WITHOUT_CSHARP // Inform the managed runtime about the window (game can link GUI to it) auto scriptingClass = Scripting::GetStaticClass(); ASSERT(scriptingClass); @@ -613,7 +613,7 @@ void EngineImpl::InitMainWindow() ASSERT(setWindowMethod); void* params[1]; params[0] = Engine::MainWindow->GetOrCreateManagedInstance(); - MonoObject* exception = nullptr; + MObject* exception = nullptr; setWindowMethod->Invoke(nullptr, params, &exception); if (exception) { diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index ca42755a4..ea26c4ea6 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -11,7 +11,9 @@ #include "Engine/Renderer/RenderList.h" #include "Engine/Serialization/MemoryReadStream.h" #include "Engine/Threading/Threading.h" +#if USE_MONO #include +#endif namespace { @@ -106,6 +108,8 @@ namespace return mesh->UpdateMesh(vertexCount, triangleCount, (VB0ElementType*)vertices, vb1.Get(), vb2.HasItems() ? vb2.Get() : nullptr, triangles); } +#if !COMPILE_WITHOUT_CSHARP + template bool UpdateMesh(Mesh* mesh, uint32 vertexCount, uint32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj) { @@ -132,6 +136,8 @@ namespace return mesh->UpdateTriangles(triangleCount, ib); } + +#endif } bool Mesh::HasVertexColors() const @@ -591,6 +597,8 @@ ScriptingObject* Mesh::GetParentModel() return _model; } +#if !COMPILE_WITHOUT_CSHARP + bool Mesh::UpdateMeshUInt(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj) { return ::UpdateMesh(this, (uint32)vertexCount, (uint32)triangleCount, verticesObj, trianglesObj, normalsObj, tangentsObj, uvObj, colorsObj); @@ -763,3 +771,5 @@ bool Mesh::DownloadBuffer(bool forceGpu, MonoArray* resultObj, int32 typeI) ConvertMeshData(mesh, type, resultObj, data.Get()); return false; } + +#endif diff --git a/Source/Engine/Graphics/Models/Mesh.h b/Source/Engine/Graphics/Models/Mesh.h index 483f15153..7cda9031f 100644 --- a/Source/Engine/Graphics/Models/Mesh.h +++ b/Source/Engine/Graphics/Models/Mesh.h @@ -404,9 +404,11 @@ private: // Internal bindings API_FUNCTION(NoProxy) ScriptingObject* GetParentModel(); +#if !COMPILE_WITHOUT_CSHARP API_FUNCTION(NoProxy) bool UpdateMeshUInt(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj); API_FUNCTION(NoProxy) bool UpdateMeshUShort(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj); API_FUNCTION(NoProxy) bool UpdateTrianglesUInt(int32 triangleCount, MonoArray* trianglesObj); API_FUNCTION(NoProxy) bool UpdateTrianglesUShort(int32 triangleCount, MonoArray* trianglesObj); API_FUNCTION(NoProxy) bool DownloadBuffer(bool forceGpu, MonoArray* resultObj, int32 typeI); +#endif }; diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp index e75136cf2..7e8feaf86 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp @@ -11,7 +11,9 @@ #include "Engine/Serialization/MemoryReadStream.h" #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Threading/Threading.h" +#if USE_MONO #include +#endif void SkinnedMesh::Init(SkinnedModel* model, int32 lodIndex, int32 index, int32 materialSlotIndex, const BoundingBox& box, const BoundingSphere& sphere) { @@ -316,6 +318,8 @@ ScriptingObject* SkinnedMesh::GetParentModel() return _model; } +#if !COMPILE_WITHOUT_CSHARP + template bool UpdateMesh(SkinnedMesh* mesh, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* blendIndicesObj, MonoArray* blendWeightsObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj) { @@ -561,3 +565,5 @@ bool SkinnedMesh::DownloadBuffer(bool forceGpu, MonoArray* resultObj, int32 type ConvertMeshData(mesh, type, resultObj, data.Get()); return false; } + +#endif diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.h b/Source/Engine/Graphics/Models/SkinnedMesh.h index 462286b44..61ea497c6 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.h +++ b/Source/Engine/Graphics/Models/SkinnedMesh.h @@ -258,7 +258,9 @@ private: // Internal bindings API_FUNCTION(NoProxy) ScriptingObject* GetParentModel(); +#if !COMPILE_WITHOUT_CSHARP API_FUNCTION(NoProxy) bool UpdateMeshUInt(MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* blendIndicesObj, MonoArray* blendWeightsObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj); API_FUNCTION(NoProxy) bool UpdateMeshUShort(MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* blendIndicesObj, MonoArray* blendWeightsObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj); API_FUNCTION(NoProxy) bool DownloadBuffer(bool forceGpu, MonoArray* resultObj, int32 typeI); +#endif }; diff --git a/Source/Engine/Graphics/RenderTask.cpp b/Source/Engine/Graphics/RenderTask.cpp index 05b261728..4ce50b94f 100644 --- a/Source/Engine/Graphics/RenderTask.cpp +++ b/Source/Engine/Graphics/RenderTask.cpp @@ -20,13 +20,17 @@ #include "Engine/Scripting/Script.h" #include "Engine/Scripting/BinaryModule.h" #include "Engine/Threading/Threading.h" +#if USE_MONO #include +#endif #if USE_EDITOR #include "Engine/Renderer/Lightmaps.h" #else #include "Engine/Engine/Screen.h" #endif +#if USE_MONO + // TODO: use API for events and remove this manual wrapper code class RenderContextInternal { @@ -53,6 +57,8 @@ namespace } } +#endif + Array RenderTask::Tasks; CriticalSection RenderTask::TasksLocker; int32 RenderTask::TasksDoneLastFrame; @@ -174,7 +180,7 @@ void ManagedPostProcessEffect::FetchInfo() args[0] = Target->GetOrCreateManagedInstance(); args[1] = &_location; args[2] = &_useSingleTarget; - MonoObject* exception = nullptr; + MObject* exception = nullptr; FetchInfoManaged->Invoke(nullptr, args, &exception); if (exception) DebugLog::LogException(exception); @@ -187,6 +193,7 @@ bool ManagedPostProcessEffect::IsLoaded() const void ManagedPostProcessEffect::Render(RenderContext& renderContext, GPUTexture* input, GPUTexture* output) { +#if USE_MONO const auto context = GPUDevice::Instance->GetMainContext(); auto inputObj = ScriptingObject::ToManaged(input); auto outputObj = ScriptingObject::ToManaged(output); @@ -203,10 +210,11 @@ void ManagedPostProcessEffect::Render(RenderContext& renderContext, GPUTexture* params[1] = &tmp; params[2] = inputObj; params[3] = outputObj; - MonoObject* exception = nullptr; + MObject* exception = nullptr; renderMethod->InvokeVirtual(Target->GetOrCreateManagedInstance(), params, &exception); if (exception) DebugLog::LogException(exception); +#endif } SceneRenderTask::SceneRenderTask(const SpawnParams& params) @@ -340,6 +348,8 @@ void SceneRenderTask::OnBegin(GPUContext* context) } // Get custom and global PostFx + CustomPostFx.Clear(); +#if !COMPILE_WITHOUT_CSHARP // TODO: move postFx in SceneRenderTask from C# to C++ static MMethod* GetPostFxManaged = GetStaticClass()->GetMethod("GetPostFx", 1); if (GetPostFxManaged) @@ -347,7 +357,8 @@ void SceneRenderTask::OnBegin(GPUContext* context) int32 count = 0; void* params[1]; params[0] = &count; - MonoObject* exception = nullptr; + MObject* exception = nullptr; +#if USE_MONO const auto objects = (MonoArray*)GetPostFxManaged->Invoke(GetOrCreateManagedInstance(), params, &exception); if (exception) DebugLog::LogException(exception); @@ -359,9 +370,9 @@ void SceneRenderTask::OnBegin(GPUContext* context) if (postFx.Target) postFx.FetchInfo(); } +#endif } - else - CustomPostFx.Clear(); +#endif // Setup render buffers for the output rendering resolution if (Output) diff --git a/Source/Engine/Level/Actors/Spline.cpp b/Source/Engine/Level/Actors/Spline.cpp index 4c0d21cd7..d1db302a8 100644 --- a/Source/Engine/Level/Actors/Spline.cpp +++ b/Source/Engine/Level/Actors/Spline.cpp @@ -4,7 +4,9 @@ #include "Engine/Serialization/Serialization.h" #include "Engine/Animations/CurveSerialization.h" #include "Engine/Core/Math/Matrix.h" +#if USE_MONO #include +#endif Spline::Spline(const SpawnParams& params) : Actor(params) @@ -437,6 +439,8 @@ void Spline::UpdateSpline() SplineUpdated(); } +#if !COMPILE_WITHOUT_CSHARP + void Spline::GetKeyframes(MonoArray* data) { Platform::MemoryCopy(mono_array_addr_with_size(data, sizeof(Keyframe), 0), Curve.GetKeyframes().Get(), sizeof(Keyframe) * Curve.GetKeyframes().Count()); @@ -450,6 +454,8 @@ void Spline::SetKeyframes(MonoArray* data) UpdateSpline(); } +#endif + #if USE_EDITOR #include "Engine/Debug/DebugDraw.h" diff --git a/Source/Engine/Level/Actors/Spline.h b/Source/Engine/Level/Actors/Spline.h index 79fce685d..2637ebe28 100644 --- a/Source/Engine/Level/Actors/Spline.h +++ b/Source/Engine/Level/Actors/Spline.h @@ -368,8 +368,10 @@ protected: private: // Internal bindings +#if !COMPILE_WITHOUT_CSHARP API_FUNCTION(NoProxy) void GetKeyframes(MonoArray* data); API_FUNCTION(NoProxy) void SetKeyframes(MonoArray* data); +#endif public: diff --git a/Source/Engine/Level/SceneObject.cpp b/Source/Engine/Level/SceneObject.cpp index 9267f171f..a52d56301 100644 --- a/Source/Engine/Level/SceneObject.cpp +++ b/Source/Engine/Level/SceneObject.cpp @@ -117,6 +117,7 @@ void SceneObject::Serialize(SerializeStream& stream, const void* otherObj) stream.Guid(_parent->GetID()); } +#if !COMPILE_WITHOUT_CSHARP // Handle C# objects data serialization if (Flags & ObjectFlags::IsManagedType) { @@ -130,6 +131,7 @@ void SceneObject::Serialize(SerializeStream& stream, const void* otherObj) ManagedSerialization::Serialize(stream, GetOrCreateManagedInstance()); } } +#endif // Handle custom scripting objects data serialization if (Flags & ObjectFlags::IsCustomScriptingType) @@ -146,6 +148,7 @@ void SceneObject::Deserialize(DeserializeStream& stream, ISerializeModifier* mod // _prefabID is deserialized by Actor/Script impl DESERIALIZE_MEMBER(PrefabObjectID, _prefabObjectID); +#if !COMPILE_WITHOUT_CSHARP // Handle C# objects data serialization if (Flags & ObjectFlags::IsManagedType) { @@ -155,6 +158,7 @@ void SceneObject::Deserialize(DeserializeStream& stream, ISerializeModifier* mod ManagedSerialization::Deserialize(v->value, GetOrCreateManagedInstance()); } } +#endif // Handle custom scripting objects data serialization if (Flags & ObjectFlags::IsCustomScriptingType) diff --git a/Source/Engine/Localization/CultureInfo.cpp b/Source/Engine/Localization/CultureInfo.cpp index d46bacfbe..94e2f267b 100644 --- a/Source/Engine/Localization/CultureInfo.cpp +++ b/Source/Engine/Localization/CultureInfo.cpp @@ -47,8 +47,6 @@ CultureInfo::CultureInfo(int32 lcid) break; } } -#else -#error "Missing CultureInfo implementation." #endif if (!_data) { @@ -89,8 +87,6 @@ CultureInfo::CultureInfo(const StringAnsiView& name) break; } } -#else -#error "Missing CultureInfo implementation." #endif if (!_data) { @@ -132,8 +128,6 @@ bool CultureInfo::IsRightToLeft() const const auto data = static_cast(_data); if (data) return data->text_info.is_right_to_left ? true : false; -#else -#error "Missing CultureInfo implementation." #endif return false; } diff --git a/Source/Engine/Platform/Base/WindowBase.cpp b/Source/Engine/Platform/Base/WindowBase.cpp index 19dfb3b27..8df7ae6d1 100644 --- a/Source/Engine/Platform/Base/WindowBase.cpp +++ b/Source/Engine/Platform/Base/WindowBase.cpp @@ -14,8 +14,11 @@ #include "Engine/Scripting/ManagedCLR/MUtils.h" #include "Engine/Scripting/ManagedCLR/MMethod.h" #include "Engine/Scripting/ManagedCLR/MClass.h" +#if USE_MONO #include +#endif +#if USE_MONO // Helper macros for calling C# events #define BEGIN_INVOKE_EVENT(name, paramsCount) \ auto managedInstance = GetManagedInstance(); \ @@ -42,7 +45,7 @@ params[0] = param0; \ params[1] = param1; \ params[2] = param2; \ - MonoObject* exception = nullptr; \ + MObject* exception = nullptr; \ _method_##name->Invoke(managedInstance, params, &exception); \ END_INVOKE_EVENT(name) #define INVOKE_EVENT_PARAMS_3(name, param0, param1, param2) INVOKE_EVENT(name, 3, param0, param1, param2) @@ -69,11 +72,19 @@ for (int32 i = 0; i < outputData.Count(); i++) \ *(MonoString**)mono_array_addr_with_size(outputDataMono, sizeof(MonoString*), i) = MUtils::ToString(outputData[i]); \ params[2] = outputDataMono; \ - MonoObject* exception = nullptr; \ + MObject* exception = nullptr; \ auto resultObj = _method_##name->Invoke(GetManagedInstance(), params, &exception); \ if (resultObj) \ result = (DragDropEffect)MUtils::Unbox(resultObj); \ END_INVOKE_EVENT(name) +#else +#define INVOKE_EVENT(name, paramsCount, param0, param1, param2) +#define INVOKE_EVENT_PARAMS_3(name, param0, param1, param2) INVOKE_EVENT(name, 3, param0, param1, param2) +#define INVOKE_EVENT_PARAMS_2(name, param0, param1) INVOKE_EVENT(name, 2, param0, param1, nullptr) +#define INVOKE_EVENT_PARAMS_1(name, param0) INVOKE_EVENT(name, 1, param0, nullptr, nullptr) +#define INVOKE_EVENT_PARAMS_0(name) INVOKE_EVENT(name, 0, nullptr, nullptr, nullptr) +#define INVOKE_DRAG_EVENT(name) +#endif WindowBase::WindowBase(const CreateWindowSettings& settings) : PersistentScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) diff --git a/Source/Engine/Scripting/BinaryModule.cpp b/Source/Engine/Scripting/BinaryModule.cpp index c4f58274a..4a6eb2f5f 100644 --- a/Source/Engine/Scripting/BinaryModule.cpp +++ b/Source/Engine/Scripting/BinaryModule.cpp @@ -21,8 +21,12 @@ Delegate, ScriptingTypeHandle, StringView> Scrip ManagedBinaryModule* GetBinaryModuleCorlib() { +#if COMPILE_WITHOUT_CSHARP + return nullptr; +#else static ManagedBinaryModule assembly("corlib", MAssemblyOptions(false)); // Don't precache all corlib classes return &assembly; +#endif } ScriptingTypeHandle::ScriptingTypeHandle(const ScriptingTypeInitializer& initializer) @@ -698,6 +702,8 @@ ScriptingObject* ManagedBinaryModule::ManagedObjectSpawn(const ScriptingObjectSp return object; } +#if !COMPILE_WITHOUT_CSHARP + namespace { MMethod* FindMethod(MClass* mclass, const MMethod* referenceMethod) @@ -719,6 +725,8 @@ namespace } } +#endif + MMethod* ManagedBinaryModule::FindMethod(MClass* mclass, const ScriptingTypeMethodSignature& signature) { if (!mclass) @@ -726,6 +734,7 @@ MMethod* ManagedBinaryModule::FindMethod(MClass* mclass, const ScriptingTypeMeth const auto& methods = mclass->GetMethods(); for (MMethod* method : methods) { +#if USE_MONO MonoMethodSignature* sig = mono_method_signature(method->GetNative()); if (method->IsStatic() != signature.IsStatic || method->GetName() != signature.Name || @@ -746,10 +755,13 @@ MMethod* ManagedBinaryModule::FindMethod(MClass* mclass, const ScriptingTypeMeth } if (isValid && MUtils::GetClass(signature.ReturnType) == mono_class_from_mono_type(mono_signature_get_return_type(sig))) return method; +#endif } return nullptr; } +#if USE_MONO + ManagedBinaryModule* ManagedBinaryModule::FindModule(MonoClass* klass) { // TODO: consider caching lookup table MonoImage* -> ManagedBinaryModule* @@ -782,6 +794,8 @@ ScriptingTypeHandle ManagedBinaryModule::FindType(MonoClass* klass) return ScriptingTypeHandle(); } +#endif + void ManagedBinaryModule::OnLoading(MAssembly* assembly) { PROFILE_CPU(); @@ -793,6 +807,7 @@ void ManagedBinaryModule::OnLoading(MAssembly* assembly) void ManagedBinaryModule::OnLoaded(MAssembly* assembly) { +#if !COMPILE_WITHOUT_CSHARP PROFILE_CPU(); ASSERT(ClassToTypeIndex.IsEmpty()); @@ -849,10 +864,12 @@ void ManagedBinaryModule::OnLoaded(MAssembly* assembly) InitType(mclass); } } +#endif } void ManagedBinaryModule::InitType(MClass* mclass) { +#if !COMPILE_WITHOUT_CSHARP // Skip if already initialized const MString& typeName = mclass->GetFullName(); if (TypeNameToTypeIndex.ContainsKey(typeName)) @@ -992,6 +1009,7 @@ void ManagedBinaryModule::InitType(MClass* mclass) // Move to the next entry (table is null terminated) scriptVTable++; } +#endif } void ManagedBinaryModule::OnUnloading(MAssembly* assembly) @@ -1020,7 +1038,9 @@ void ManagedBinaryModule::OnUnloading(MAssembly* assembly) type.Script.ScriptVTable = nullptr; } } +#if !COMPILE_WITHOUT_CSHARP ClassToTypeIndex.Clear(); +#endif } const StringAnsi& ManagedBinaryModule::GetName() const @@ -1030,7 +1050,11 @@ const StringAnsi& ManagedBinaryModule::GetName() const bool ManagedBinaryModule::IsLoaded() const { +#if COMPILE_WITHOUT_CSHARP + return true; +#else return Assembly->IsLoaded(); +#endif } void* ManagedBinaryModule::FindMethod(const ScriptingTypeHandle& typeHandle, const StringAnsiView& name, int32 numParams) @@ -1047,6 +1071,7 @@ void* ManagedBinaryModule::FindMethod(const ScriptingTypeHandle& typeHandle, con bool ManagedBinaryModule::InvokeMethod(void* method, const Variant& instance, Span paramValues, Variant& result) { +#if USE_MONO const auto mMethod = (MMethod*)method; MonoMethodSignature* signature = mono_method_signature(mMethod->GetNative()); void* signatureParams = nullptr; @@ -1101,7 +1126,7 @@ bool ManagedBinaryModule::InvokeMethod(void* method, const Variant& instance, Sp } // Invoke the method - MonoObject* exception = nullptr; + MObject* exception = nullptr; MonoObject* resultObject = withInterfaces ? mMethod->InvokeVirtual((MonoObject*)mInstance, params, &exception) : mMethod->Invoke(mInstance, params, &exception); if (exception) { @@ -1164,10 +1189,14 @@ bool ManagedBinaryModule::InvokeMethod(void* method, const Variant& instance, Sp } return false; +#else + return true; +#endif } void ManagedBinaryModule::GetMethodSignature(void* method, ScriptingTypeMethodSignature& signature) { +#if USE_MONO const auto mMethod = (MMethod*)method; signature.Name = mMethod->GetName(); signature.IsStatic = mMethod->IsStatic(); @@ -1183,6 +1212,7 @@ void ManagedBinaryModule::GetMethodSignature(void* method, ScriptingTypeMethodSi param.Type = MoveTemp(MUtils::UnboxVariantType(((MonoType**)signatureParams)[paramIdx])); param.IsOut = mono_signature_param_is_out(sig, paramIdx) != 0; } +#endif } void* ManagedBinaryModule::FindField(const ScriptingTypeHandle& typeHandle, const StringAnsiView& name) @@ -1193,14 +1223,17 @@ void* ManagedBinaryModule::FindField(const ScriptingTypeHandle& typeHandle, cons void ManagedBinaryModule::GetFieldSignature(void* field, ScriptingTypeFieldSignature& fieldSignature) { +#if USE_MONO const auto mField = (MField*)field; fieldSignature.Name = mField->GetName(); fieldSignature.ValueType = MoveTemp(MUtils::UnboxVariantType(mField->GetType().GetNative())); fieldSignature.IsStatic = mField->IsStatic(); +#endif } bool ManagedBinaryModule::GetFieldValue(void* field, const Variant& instance, Variant& result) { +#if USE_MONO const auto mField = (MField*)field; // Get instance object @@ -1225,10 +1258,14 @@ bool ManagedBinaryModule::GetFieldValue(void* field, const Variant& instance, Va MonoObject* resultObject = mField->GetValueBoxed(instanceObject); result = MUtils::UnboxVariant(resultObject); return false; +#else + return true; +#endif } bool ManagedBinaryModule::SetFieldValue(void* field, const Variant& instance, Variant& value) { +#if USE_MONO const auto mField = (MField*)field; // Get instance object @@ -1253,6 +1290,9 @@ bool ManagedBinaryModule::SetFieldValue(void* field, const Variant& instance, Va bool failed = false; mField->SetValue(instanceObject, MUtils::VariantToManagedArgPtr(value, mField->GetType(), failed)); return failed; +#else + return true; +#endif } void ManagedBinaryModule::Destroy(bool isReloading) diff --git a/Source/Engine/Scripting/BinaryModule.h b/Source/Engine/Scripting/BinaryModule.h index 725400d38..fabbd1663 100644 --- a/Source/Engine/Scripting/BinaryModule.h +++ b/Source/Engine/Scripting/BinaryModule.h @@ -290,15 +290,19 @@ public: /// MAssembly* Assembly; +#if !COMPILE_WITHOUT_CSHARP /// /// The scripting types cache that maps the managed class to the scripting type index. Build after assembly is loaded and scripting types get the managed classes information. /// Dictionary ClassToTypeIndex; +#endif static ScriptingObject* ManagedObjectSpawn(const ScriptingObjectSpawnParams& params); static MMethod* FindMethod(MClass* mclass, const ScriptingTypeMethodSignature& signature); +#if USE_MONO static ManagedBinaryModule* FindModule(MonoClass* klass); static ScriptingTypeHandle FindType(MonoClass* klass); +#endif private: diff --git a/Source/Engine/Scripting/InternalCalls.h b/Source/Engine/Scripting/InternalCalls.h index 3a1c33160..d258a9f14 100644 --- a/Source/Engine/Scripting/InternalCalls.h +++ b/Source/Engine/Scripting/InternalCalls.h @@ -5,6 +5,9 @@ #include "Engine/Debug/DebugLog.h" #include "Engine/Core/Log.h" #include "ScriptingType.h" +#include "Types.h" + +#if USE_MONO extern "C" FLAXENGINE_API void mono_add_internal_call(const char* name, const void* method); #define ADD_INTERNAL_CALL(fullName, method) mono_add_internal_call(fullName, (const void*)method) @@ -46,3 +49,13 @@ extern "C" FLAXENGINE_API void mono_add_internal_call(const char* name, const vo } #endif + +#else + +#define ADD_INTERNAL_CALL(fullName, method) +#define INTERNAL_CALL_CHECK(obj) +#define INTERNAL_CALL_CHECK_EXP(expression) +#define INTERNAL_CALL_CHECK_RETURN(obj, defaultValue) +#define INTERNAL_CALL_CHECK_EXP_RETURN(expression, defaultValue) + +#endif diff --git a/Source/Engine/Scripting/InternalCalls/EngineInternalCalls.cpp b/Source/Engine/Scripting/InternalCalls/EngineInternalCalls.cpp index 814b20dcd..f41c13819 100644 --- a/Source/Engine/Scripting/InternalCalls/EngineInternalCalls.cpp +++ b/Source/Engine/Scripting/InternalCalls/EngineInternalCalls.cpp @@ -6,6 +6,8 @@ #include "Engine/Scripting/MException.h" #include "Engine/Scripting/ManagedCLR/MUtils.h" +#if USE_MONO + namespace UtilsInternal { MonoObject* ExtractArrayFromList(MonoObject* obj) @@ -70,9 +72,12 @@ namespace FlaxLogWriterInternal } } +#endif + void registerFlaxEngineInternalCalls() { AnimGraphExecutor::initRuntime(); +#if USE_MONO ADD_INTERNAL_CALL("FlaxEngine.Utils::MemoryCopy", &Platform::MemoryCopy); ADD_INTERNAL_CALL("FlaxEngine.Utils::MemoryClear", &Platform::MemoryClear); ADD_INTERNAL_CALL("FlaxEngine.Utils::MemoryCompare", &Platform::MemoryCompare); @@ -81,4 +86,5 @@ void registerFlaxEngineInternalCalls() ADD_INTERNAL_CALL("FlaxEngine.DebugLogHandler::Internal_Log", &DebugLogHandlerInternal::Log); ADD_INTERNAL_CALL("FlaxEngine.DebugLogHandler::Internal_LogException", &DebugLogHandlerInternal::LogException); ADD_INTERNAL_CALL("FlaxEngine.FlaxLogWriter::Internal_WriteStringToLog", &FlaxLogWriterInternal::WriteStringToLog); +#endif } diff --git a/Source/Engine/Scripting/InternalCalls/ManagedBitArray.h b/Source/Engine/Scripting/InternalCalls/ManagedBitArray.h index d65f6bb55..d600d63fe 100644 --- a/Source/Engine/Scripting/InternalCalls/ManagedBitArray.h +++ b/Source/Engine/Scripting/InternalCalls/ManagedBitArray.h @@ -8,6 +8,7 @@ #include "Engine/Scripting/ManagedCLR/MClass.h" #include "Engine/Scripting/ManagedCLR/MField.h" #include "Engine/Scripting/BinaryModule.h" +#if USE_MONO #include #include #include @@ -15,7 +16,7 @@ struct ManagedBitArray { template - static MonoObject* ToManaged(const BitArray& data) + static MObject* ToManaged(const BitArray& data) { #if 0 // TODO: use actual System.Collections.BitArray for BitArray interop @@ -53,3 +54,5 @@ struct ManagedBitArray #endif } }; + +#endif diff --git a/Source/Engine/Scripting/InternalCalls/ManagedDictionary.h b/Source/Engine/Scripting/InternalCalls/ManagedDictionary.h index 6b9743709..2c00918d0 100644 --- a/Source/Engine/Scripting/InternalCalls/ManagedDictionary.h +++ b/Source/Engine/Scripting/InternalCalls/ManagedDictionary.h @@ -11,6 +11,7 @@ #include "Engine/Scripting/ManagedCLR/MMethod.h" #include "Engine/Scripting/ManagedCLR/MAssembly.h" #include "Engine/Scripting/MException.h" +#if USE_MONO #include struct FLAXENGINE_API ManagedDictionary @@ -93,7 +94,7 @@ struct FLAXENGINE_API ManagedDictionary void* params[2]; params[0] = genericType; params[1] = genericArgs; - MonoObject* exception = nullptr; + MObject* exception = nullptr; auto dictionaryType = makeGenericMethod->Invoke(nullptr, params, &exception); if (exception) { @@ -127,7 +128,7 @@ struct FLAXENGINE_API ManagedDictionary params[0] = Instance; params[1] = key; params[2] = value; - MonoObject* exception = nullptr; + MObject* exception = nullptr; mono_runtime_invoke(addDictionaryItemMethod->GetNative(), Instance, params, &exception); if (exception) { @@ -159,3 +160,5 @@ struct FLAXENGINE_API ManagedDictionary return mono_runtime_invoke(getItemMethod, Instance, params, nullptr); } }; + +#endif diff --git a/Source/Engine/Scripting/MException.cpp b/Source/Engine/Scripting/MException.cpp index 32e24326e..2e64e547b 100644 --- a/Source/Engine/Scripting/MException.cpp +++ b/Source/Engine/Scripting/MException.cpp @@ -2,11 +2,14 @@ #include "MException.h" #include "ManagedCLR/MUtils.h" +#if USE_MONO #include +#endif -MException::MException(MonoObject* exception) +MException::MException(MObject* exception) : InnerException(nullptr) { +#if USE_MONO ASSERT(exception); MonoClass* exceptionClass = mono_object_get_class(exception); @@ -25,6 +28,7 @@ MException::MException(MonoObject* exception) MonoObject* innerException = (MonoObject*)mono_runtime_invoke(innerExceptionGetter, exception, nullptr, nullptr); if (innerException) InnerException = New(innerException); +#endif } MException::~MException() diff --git a/Source/Engine/Scripting/MException.h b/Source/Engine/Scripting/MException.h index 068f96768..ab16e25f7 100644 --- a/Source/Engine/Scripting/MException.h +++ b/Source/Engine/Scripting/MException.h @@ -30,6 +30,7 @@ public: public: +#if USE_MONO /// /// Initializes a new instance of the class. /// @@ -38,12 +39,13 @@ public: : MException((MonoObject*)exception) { } +#endif /// /// Initializes a new instance of the class. /// /// The exception object. - explicit MException(MonoObject* exception); + explicit MException(MObject* exception); /// /// Disposes a instance of the class. diff --git a/Source/Engine/Scripting/MainThreadManagedInvokeAction.cpp b/Source/Engine/Scripting/MainThreadManagedInvokeAction.cpp index 2ec1444a7..3cd9bc5f0 100644 --- a/Source/Engine/Scripting/MainThreadManagedInvokeAction.cpp +++ b/Source/Engine/Scripting/MainThreadManagedInvokeAction.cpp @@ -5,7 +5,7 @@ #include "Engine/Scripting/ScriptingCalls.h" #include "MException.h" -MainThreadManagedInvokeAction* MainThreadManagedInvokeAction::Invoke(MMethod* method, MonoObject* instance, LogType exceptionLevel) +MainThreadManagedInvokeAction* MainThreadManagedInvokeAction::Invoke(MMethod* method, MObject* instance, LogType exceptionLevel) { ASSERT_LOW_LAYER(method != nullptr); @@ -23,7 +23,7 @@ MainThreadManagedInvokeAction* MainThreadManagedInvokeAction::Invoke(MMethod* me } } -MainThreadManagedInvokeAction* MainThreadManagedInvokeAction::Invoke(MMethod* method, ParamsBuilder& params, MonoObject* instance, LogType exceptionLevel) +MainThreadManagedInvokeAction* MainThreadManagedInvokeAction::Invoke(MMethod* method, ParamsBuilder& params, MObject* instance, LogType exceptionLevel) { ASSERT_LOW_LAYER(method != nullptr); @@ -59,14 +59,14 @@ MainThreadManagedInvokeAction* MainThreadManagedInvokeAction::Invoke(void* metho } } -void MainThreadManagedInvokeAction::InvokeNow(MMethod* method, ParamsBuilder& params, MonoObject* instance, LogType exceptionLevel) +void MainThreadManagedInvokeAction::InvokeNow(MMethod* method, ParamsBuilder& params, MObject* instance, LogType exceptionLevel) { ASSERT_LOW_LAYER(method != nullptr); void* paramsData[8]; params.GetParams(paramsData); - MonoObject* exception = nullptr; + MObject* exception = nullptr; method->Invoke(instance, paramsData, &exception); if (exception) { @@ -82,14 +82,13 @@ bool MainThreadManagedInvokeAction::Run() void* paramsData[8]; _params.GetParams(paramsData); - MonoObject* exception = nullptr; + MObject* exception = nullptr; if (_method) { _method->Invoke(_instance, paramsData, &exception); } - else + else if (_methodThunk) { - ASSERT(_methodThunk); switch (_params.Count) { case 0: diff --git a/Source/Engine/Scripting/MainThreadManagedInvokeAction.h b/Source/Engine/Scripting/MainThreadManagedInvokeAction.h index 71ea24595..caadffc5e 100644 --- a/Source/Engine/Scripting/MainThreadManagedInvokeAction.h +++ b/Source/Engine/Scripting/MainThreadManagedInvokeAction.h @@ -71,6 +71,7 @@ public: AddParam(val); } +#if USE_MONO FORCE_INLINE void AddParam(const String& value) { MonoString* val = MUtils::ToString(value); @@ -94,6 +95,7 @@ public: MonoString* val = MUtils::ToString(value, domain); AddParam(val); } +#endif void GetParams(void* params[8]) { @@ -109,7 +111,7 @@ public: private: - MonoObject* _instance; + MObject* _instance; MMethod* _method; void* _methodThunk; LogType _exceptionLevel; @@ -117,7 +119,7 @@ private: public: - MainThreadManagedInvokeAction(MonoObject* instance, MMethod* method, LogType exceptionLevel) + MainThreadManagedInvokeAction(MObject* instance, MMethod* method, LogType exceptionLevel) : _instance(instance) , _method(method) , _methodThunk(nullptr) @@ -126,7 +128,7 @@ public: { } - MainThreadManagedInvokeAction(MonoObject* instance, MMethod* method, LogType exceptionLevel, const ParamsBuilder& params) + MainThreadManagedInvokeAction(MObject* instance, MMethod* method, LogType exceptionLevel, const ParamsBuilder& params) : _instance(instance) , _method(method) , _methodThunk(nullptr) @@ -153,7 +155,7 @@ public: /// The managed instance object. /// The exception logging error level. /// The created task. - static MainThreadManagedInvokeAction* Invoke(MMethod* method, MonoObject* instance = nullptr, LogType exceptionLevel = LogType::Error); + static MainThreadManagedInvokeAction* Invoke(MMethod* method, MObject* instance = nullptr, LogType exceptionLevel = LogType::Error); /// /// Starts the new task or invokes this action now if already running on a main thread. @@ -163,7 +165,7 @@ public: /// The managed instance object. /// The exception logging error level. /// The created task. - static MainThreadManagedInvokeAction* Invoke(MMethod* method, ParamsBuilder& params, MonoObject* instance = nullptr, LogType exceptionLevel = LogType::Error); + static MainThreadManagedInvokeAction* Invoke(MMethod* method, ParamsBuilder& params, MObject* instance = nullptr, LogType exceptionLevel = LogType::Error); /// /// Starts the new task or invokes this action now if already running on a main thread. @@ -181,7 +183,7 @@ public: /// The method parameters. /// The managed instance object. /// The exception logging error level. - static void InvokeNow(MMethod* method, ParamsBuilder& params, MonoObject* instance = nullptr, LogType exceptionLevel = LogType::Error); + static void InvokeNow(MMethod* method, ParamsBuilder& params, MObject* instance = nullptr, LogType exceptionLevel = LogType::Error); protected: diff --git a/Source/Engine/Scripting/ManagedCLR/MAssembly.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MAssembly.cpp similarity index 98% rename from Source/Engine/Scripting/ManagedCLR/MAssembly.Mono.cpp rename to Source/Engine/Scripting/ManagedCLR/MAssembly.cpp index d73dc8a47..6b0cc815b 100644 --- a/Source/Engine/Scripting/ManagedCLR/MAssembly.Mono.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MAssembly.cpp @@ -1,9 +1,6 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "MAssembly.h" - -#if USE_MONO - #include "MClass.h" #include "MDomain.h" #include "MUtils.h" @@ -19,14 +16,14 @@ #include "Engine/Platform/File.h" #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Threading/Threading.h" +#if USE_MONO #include #include #include +#endif MAssembly::MAssembly(MDomain* domain, const StringAnsiView& name, const MAssemblyOptions& options) - : _monoAssembly(nullptr) - , _monoImage(nullptr) - , _domain(domain) + : _domain(domain) , _isLoaded(false) , _isLoading(false) , _isDependency(false) @@ -83,6 +80,8 @@ bool MAssembly::Load(const String& assemblyPath) return false; } +#if USE_MONO + bool MAssembly::Load(MonoImage* monoImage) { if (IsLoaded()) @@ -116,6 +115,8 @@ bool MAssembly::Load(MonoImage* monoImage) return false; } +#endif + void MAssembly::Unload(bool isReloading) { if (!IsLoaded()) @@ -125,6 +126,7 @@ void MAssembly::Unload(bool isReloading) Unloading(this); // Close runtime +#if USE_MONO if (_monoImage) { if (isReloading) @@ -143,6 +145,7 @@ void MAssembly::Unload(bool isReloading) _monoAssembly = nullptr; _monoImage = nullptr; } +#endif // Cleanup _debugData.Resize(0); @@ -190,6 +193,8 @@ MClass* MAssembly::GetClass(const StringAnsiView& fullname) const return result; } +#if USE_MONO + MClass* MAssembly::GetClass(MonoClass* monoClass) const { if (monoClass == nullptr || !IsLoaded() || mono_class_get_image(monoClass) != _monoImage) @@ -226,11 +231,16 @@ MonoReflectionAssembly* MAssembly::GetNative() const return mono_assembly_get_object(mono_domain_get(), _monoAssembly); } +#endif + const MAssembly::ClassesDictionary& MAssembly::GetClasses() const { if (_hasCachedClasses || !IsLoaded()) return _classes; PROFILE_CPU(); + const auto startTime = DateTime::NowUTC(); + +#if USE_MONO #if TRACY_ENABLE const StringAnsiView monoImageName(mono_image_get_name(_monoImage)); ZoneText(*monoImageName, monoImageName.Length()); @@ -239,9 +249,6 @@ const MAssembly::ClassesDictionary& MAssembly::GetClasses() const if (_hasCachedClasses) return _classes; ASSERT(_classes.IsEmpty()); - - const auto startTime = DateTime::NowUTC(); - const int32 numRows = mono_image_get_table_rows(_monoImage, MONO_TABLE_TYPEDEF); _classes.EnsureCapacity(numRows * 4); for (int32 i = 1; i < numRows; i++) // Skip class @@ -256,6 +263,7 @@ const MAssembly::ClassesDictionary& MAssembly::GetClasses() const auto mclass = New(this, klass, fullname); _classes.Add(fullname, mclass); } +#endif const auto endTime = DateTime::NowUTC(); LOG(Info, "Caching classes for assembly {0} took {1}ms", String(_name), (int32)(endTime - startTime).GetTotalMilliseconds()); @@ -271,6 +279,7 @@ const MAssembly::ClassesDictionary& MAssembly::GetClasses() const bool MAssembly::LoadDefault(const String& assemblyPath) { +#if USE_MONO // With this method of loading we need to make sure, we won't try to load assembly again if its loaded somewhere. auto assembly = mono_domain_assembly_open(_domain->GetNative(), assemblyPath.ToStringAnsi().Get()); if (!assembly) @@ -283,17 +292,18 @@ bool MAssembly::LoadDefault(const String& assemblyPath) mono_assembly_close(assembly); return true; } - - // Register in domain - _domain->_assemblies[_name] = this; - - // Set state _monoAssembly = assembly; _monoImage = assemblyImage; +#endif + + // Set state _isDependency = false; _hasCachedClasses = false; _isFileLocked = true; _assemblyPath = assemblyPath; + + // Register in domain + _domain->_assemblies[_name] = this; return false; } @@ -307,6 +317,7 @@ bool MAssembly::LoadWithImage(const String& assemblyPath) Array data; File::ReadAllBytes(assemblyPath, data); +#if USE_MONO // Init Mono image MonoImageOpenStatus status; const auto name = assemblyPath.ToStringAnsi(); @@ -359,10 +370,11 @@ bool MAssembly::LoadWithImage(const String& assemblyPath) } #endif #endif - - // Set state _monoAssembly = assembly; _monoImage = assemblyImage; +#endif + + // Set state _isDependency = false; _hasCachedClasses = false; _isFileLocked = false; @@ -379,7 +391,7 @@ void MAssembly::OnLoading() // Pick a domain if (_domain == nullptr) - _domain = MCore::Instance()->GetActiveDomain(); + _domain = MCore::GetActiveDomain(); } void MAssembly::OnLoaded(const DateTime& startTime) @@ -405,5 +417,3 @@ void MAssembly::OnLoadFailed() LoadFailed(this); } - -#endif diff --git a/Source/Engine/Scripting/ManagedCLR/MAssembly.h b/Source/Engine/Scripting/ManagedCLR/MAssembly.h index ff44f8b12..302c1679c 100644 --- a/Source/Engine/Scripting/ManagedCLR/MAssembly.h +++ b/Source/Engine/Scripting/ManagedCLR/MAssembly.h @@ -16,7 +16,6 @@ class FLAXENGINE_API MAssembly { friend MDomain; - public: typedef Dictionary ClassesDictionary; @@ -24,8 +23,8 @@ public: private: #if USE_MONO - MonoAssembly* _monoAssembly; - MonoImage* _monoImage; + MonoAssembly* _monoAssembly = nullptr; + MonoImage* _monoImage = nullptr; #endif MDomain* _domain; @@ -98,7 +97,6 @@ public: /// /// Returns true if assembly is during loading state. /// - /// True if is loading, otherwise false. FORCE_INLINE bool IsLoading() const { return _isLoading != 0; @@ -107,7 +105,6 @@ public: /// /// Returns true if assembly has been loaded. /// - /// True if is loaded, otherwise false. FORCE_INLINE bool IsLoaded() const { return _isLoaded != 0; @@ -116,7 +113,6 @@ public: /// /// Gets the assembly name. /// - /// The assembly name. FORCE_INLINE const MString& GetName() const { return _name; @@ -125,7 +121,6 @@ public: /// /// Gets the assembly name as string. /// - /// The assembly name. String ToString() const; /// @@ -134,7 +129,6 @@ public: /// /// If assembly was made from scratch (empty), path will return null. /// - /// The assembly path. FORCE_INLINE const String& GetAssemblyPath() const { return _assemblyPath; @@ -143,20 +137,15 @@ public: /// /// Gets the parent domain. /// - /// The domain object. FORCE_INLINE MDomain* GetDomain() const { return _domain; } -public: - #if USE_MONO - /// /// Gets the Mono assembly. /// - /// The Mono assembly. FORCE_INLINE MonoAssembly* GetMonoAssembly() const { return _monoAssembly; @@ -165,25 +154,22 @@ public: /// /// Gets the Mono image. /// - /// The Mono image. FORCE_INLINE MonoImage* GetMonoImage() const { return _monoImage; } - #endif -public: - /// /// Gets the options that assembly was created with. /// - /// The options. FORCE_INLINE const MAssemblyOptions& GetOptions() const { return _options; } +public: + /// /// Loads assembly for domain. /// @@ -192,14 +178,12 @@ public: bool Load(const String& assemblyPath); #if USE_MONO - /// /// Loads assembly for domain. /// /// The assembly image. /// True if cannot load, otherwise false. bool Load(MonoImage* monoImage); - #endif /// @@ -218,7 +202,6 @@ public: MClass* GetClass(const StringAnsiView& typeName) const; #if USE_MONO - /// /// Converts an internal mono representation of a class into engine class. /// @@ -231,7 +214,6 @@ public: /// /// The native assembly object. MonoReflectionAssembly* GetNative() const; - #endif /// @@ -242,8 +224,6 @@ public: private: -#if USE_MONO - /// /// Loads the assembly for domain. /// @@ -256,8 +236,6 @@ private: /// True if failed, otherwise false. bool LoadWithImage(const String& assemblyPath); -#endif - void OnLoading(); void OnLoaded(const struct DateTime& startTime); void OnLoadFailed(); diff --git a/Source/Engine/Scripting/ManagedCLR/MClass.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MClass.cpp similarity index 84% rename from Source/Engine/Scripting/ManagedCLR/MClass.Mono.cpp rename to Source/Engine/Scripting/ManagedCLR/MClass.cpp index b02580ab8..7bd79aa40 100644 --- a/Source/Engine/Scripting/ManagedCLR/MClass.Mono.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MClass.cpp @@ -1,9 +1,6 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "MClass.h" - -#if USE_MONO - #include "MType.h" #include "MTypes.h" #include "MField.h" @@ -11,16 +8,16 @@ #include "MMethod.h" #include "MEvent.h" #include "Engine/Scripting/Scripting.h" +#include "Engine/Core/Log.h" +#if USE_MONO #include #include - #define GET_CUSTOM_ATTR() (MonoCustomAttrInfo*)(_attrInfo ? _attrInfo : _attrInfo = mono_custom_attrs_from_class(_monoClass)) -#include "Engine/Core/Log.h" +#endif +#if USE_MONO MClass::MClass(const MAssembly* parentAssembly, MonoClass* monoClass, const MString& fullname) - : _monoClass(monoClass) - , _attrInfo(nullptr) - , _assembly(parentAssembly) + : _assembly(parentAssembly) , _fullname(fullname) , _visibility(MVisibility::Private) , _hasCachedProperties(false) @@ -33,9 +30,10 @@ MClass::MClass(const MAssembly* parentAssembly, MonoClass* monoClass, const MStr , _isAbstract(false) , _isInterface(false) { - ASSERT(_monoClass); + _monoClass = monoClass; + ASSERT(monoClass); - const uint32_t flags = mono_class_get_flags(_monoClass); + const uint32_t flags = mono_class_get_flags(monoClass); switch (flags & MONO_TYPE_ATTR_VISIBILITY_MASK) { @@ -67,12 +65,14 @@ MClass::MClass(const MAssembly* parentAssembly, MonoClass* monoClass, const MStr _isAbstract = !_isStatic && (flags & MONO_TYPE_ATTR_ABSTRACT) == MONO_TYPE_ATTR_ABSTRACT; _isInterface = (flags & MONO_TYPE_ATTR_CLASS_SEMANTIC_MASK) == MONO_TYPE_ATTR_INTERFACE; } +#endif MClass::~MClass() { +#if USE_MONO if (_attrInfo) mono_custom_attrs_free((MonoCustomAttrInfo*)_attrInfo); - +#endif _fields.ClearDelete(); _properties.ClearDelete(); _methods.ClearDelete(); @@ -80,11 +80,6 @@ MClass::~MClass() _events.ClearDelete(); } -MonoClass* MClass::GetNative() const -{ - return _monoClass; -} - bool MClass::IsGeneric() const { return _fullname.FindLast('`') != -1; @@ -92,45 +87,63 @@ bool MClass::IsGeneric() const MType MClass::GetType() const { +#if USE_MONO return MType(mono_class_get_type(_monoClass)); +#else + return MType(); +#endif } MClass* MClass::GetBaseClass() const { +#if USE_MONO MonoClass* monoBase = mono_class_get_parent(_monoClass); if (monoBase == nullptr) return nullptr; - return Scripting::FindClass(monoBase); +#else + return nullptr; +#endif } bool MClass::IsSubClassOf(const MClass* klass) const { +#if USE_MONO return klass && mono_class_is_subclass_of(_monoClass, klass->GetNative(), false) != 0; +#else + return false; +#endif } +#if USE_MONO bool MClass::IsSubClassOf(MonoClass* monoClass) const { return monoClass && mono_class_is_subclass_of(_monoClass, monoClass, true) != 0; } +#endif -bool MClass::IsInstanceOfType(MonoObject* object) const +bool MClass::IsInstanceOfType(MObject* object) const { if (object == nullptr) return false; - +#if USE_MONO MonoClass* monoClass = mono_object_get_class(object); return mono_class_is_subclass_of(monoClass, _monoClass, false) != 0; +#else + return false; +#endif } uint32 MClass::GetInstanceSize() const { +#if USE_MONO uint32 dummy = 0; - if (mono_class_is_valuetype(_monoClass)) return mono_class_value_size(_monoClass, &dummy); - return mono_class_instance_size(_monoClass); +#else + return 0; +#endif } MMethod* MClass::FindMethod(const char* name, int32 numParams, bool checkBaseClasses) @@ -154,6 +167,7 @@ MMethod* MClass::GetMethod(const char* name, int32 numParams) return _methods[i]; } +#if USE_MONO // Find Mono method MonoMethod* monoMethod = mono_class_get_method_from_name(_monoClass, name, numParams); if (monoMethod == nullptr) @@ -162,8 +176,10 @@ MMethod* MClass::GetMethod(const char* name, int32 numParams) // Create method auto method = New(monoMethod, name, this); _methods.Add(method); - return method; +#else + return nullptr; +#endif } const Array& MClass::GetMethods() @@ -171,6 +187,7 @@ const Array& MClass::GetMethods() if (_hasCachedMethods) return _methods; +#if USE_MONO void* iter = nullptr; MonoMethod* curClassMethod; while ((curClassMethod = mono_class_get_methods(_monoClass, &iter))) @@ -193,6 +210,7 @@ const Array& MClass::GetMethods() _methods.Add(method); } } +#endif _hasCachedMethods = true; return _methods; @@ -207,6 +225,7 @@ MField* MClass::GetField(const char* name) return _fields[i]; } +#if USE_MONO // Find mono field MonoClassField* field = mono_class_get_field_from_name(_monoClass, name); if (field == nullptr) @@ -216,6 +235,9 @@ MField* MClass::GetField(const char* name) auto mfield = New(field, name, this); _fields.Add(mfield); return mfield; +#else + return nullptr; +#endif } const Array& MClass::GetFields() @@ -223,6 +245,7 @@ const Array& MClass::GetFields() if (_hasCachedFields) return _fields; +#if USE_MONO void* iter = nullptr; MonoClassField* curClassField; while ((curClassField = mono_class_get_fields(_monoClass, &iter))) @@ -230,6 +253,7 @@ const Array& MClass::GetFields() const char* fieldName = mono_field_get_name(curClassField); GetField(fieldName); } +#endif _hasCachedFields = true; return _fields; @@ -246,34 +270,33 @@ MEvent* MClass::GetEvent(const char* name) return nullptr; } -MEvent* MClass::AddEvent(const char* name, MonoEvent* event) -{ - // Lookup for cached event - for (int32 i = 0; i < _events.Count(); i++) - { - if (_events[i]->GetName() == name) - return _events[i]; - } - - // Create field - auto result = New(event, name, this); - _events.Add(result); - - return result; -} - const Array& MClass::GetEvents() { if (_hasCachedEvents) return _events; +#if USE_MONO void* iter = nullptr; MonoEvent* curEvent; while ((curEvent = mono_class_get_events(_monoClass, &iter))) { - const char* fieldName = mono_event_get_name(curEvent); - AddEvent(fieldName, curEvent); + const char* name = mono_event_get_name(curEvent); + bool missing = true; + for (int32 i = 0; i < _events.Count(); i++) + { + if (_events[i]->GetName() == name) + { + missing = false; + break; + } + } + if (missing) + { + auto result = New(curEvent, name, this); + _events.Add(result); + } } +#endif _hasCachedEvents = true; return _events; @@ -288,6 +311,7 @@ MProperty* MClass::GetProperty(const char* name) return _properties[i]; } +#if USE_MONO // Find mono property MonoProperty* monoProperty = mono_class_get_property_from_name(_monoClass, name); if (monoProperty == nullptr) @@ -298,6 +322,9 @@ MProperty* MClass::GetProperty(const char* name) _properties.Add(mproperty); return mproperty; +#else + return nullptr; +#endif } const Array& MClass::GetProperties() @@ -305,6 +332,7 @@ const Array& MClass::GetProperties() if (_hasCachedProperties) return _properties; +#if USE_MONO void* iter = nullptr; MonoProperty* curClassProperty; while ((curClassProperty = mono_class_get_properties(_monoClass, &iter))) @@ -312,52 +340,74 @@ const Array& MClass::GetProperties() const char* propertyName = mono_property_get_name(curClassProperty); GetProperty(propertyName); } +#endif _hasCachedProperties = true; return _properties; } -MonoObject* MClass::CreateInstance() const +MObject* MClass::CreateInstance() const { +#if USE_MONO MonoObject* obj = mono_object_new(mono_domain_get(), _monoClass); if (!mono_class_is_valuetype(_monoClass)) mono_runtime_object_init(obj); return obj; +#else + return nullptr; +#endif } -MonoObject* MClass::CreateInstance(void** params, uint32 numParams) +MObject* MClass::CreateInstance(void** params, uint32 numParams) { +#if USE_MONO MonoObject* obj = mono_object_new(mono_domain_get(), _monoClass); const auto constructor = GetMethod(".ctor", numParams); ASSERT(constructor); constructor->Invoke(obj, params, nullptr); return obj; +#else + return nullptr; +#endif } bool MClass::HasAttribute(MClass* monoClass) { +#if USE_MONO MonoCustomAttrInfo* attrInfo = GET_CUSTOM_ATTR(); return attrInfo != nullptr && mono_custom_attrs_has_attr(attrInfo, monoClass->GetNative()) != 0; +#else + return false; +#endif } bool MClass::HasAttribute() { +#if USE_MONO MonoCustomAttrInfo* attrInfo = GET_CUSTOM_ATTR(); return attrInfo && attrInfo->num_attrs > 0; +#else + return false; +#endif } -MonoObject* MClass::GetAttribute(MClass* monoClass) +MObject* MClass::GetAttribute(MClass* monoClass) { +#if USE_MONO MonoCustomAttrInfo* attrInfo = GET_CUSTOM_ATTR(); return attrInfo ? mono_custom_attrs_get_attr(attrInfo, monoClass->GetNative()) : nullptr; +#else + return false; +#endif } -const Array& MClass::GetAttributes() +const Array& MClass::GetAttributes() { if (_hasCachedAttributes) return _attributes; _hasCachedAttributes = true; +#if USE_MONO MonoCustomAttrInfo* attrInfo = GET_CUSTOM_ATTR(); if (attrInfo == nullptr) return _attributes; @@ -366,9 +416,8 @@ const Array& MClass::GetAttributes() const auto length = (uint32)mono_array_length(monoAttributesArray); _attributes.Resize(length); for (uint32 i = 0; i < length; i++) - _attributes[i] = mono_array_get(monoAttributesArray, MonoObject*, i); + _attributes[i] = mono_array_get(monoAttributesArray, MonoObject *, i); mono_custom_attrs_free(attrInfo); +#endif return _attributes; } - -#endif diff --git a/Source/Engine/Scripting/ManagedCLR/MClass.h b/Source/Engine/Scripting/ManagedCLR/MClass.h index 255abd84b..245d959a2 100644 --- a/Source/Engine/Scripting/ManagedCLR/MClass.h +++ b/Source/Engine/Scripting/ManagedCLR/MClass.h @@ -14,7 +14,7 @@ private: #if USE_MONO MonoClass* _monoClass; - void* _attrInfo; + void* _attrInfo = nullptr; #endif const MAssembly* _assembly; @@ -23,7 +23,7 @@ private: Array _methods; Array _fields; Array _properties; - Array _attributes; + Array _attributes; Array _events; MVisibility _visibility; @@ -40,6 +40,7 @@ private: public: +#if USE_MONO /// /// Initializes a new instance of the class. /// @@ -47,6 +48,7 @@ public: /// The Mono class. /// The fullname. MClass(const MAssembly* parentAssembly, MonoClass* monoClass, const MString& fullname); +#endif /// /// Finalizes an instance of the class. @@ -72,12 +74,13 @@ public: } #if USE_MONO - /// /// Gets the Mono class handle. /// - MonoClass* GetNative() const; - + FORCE_INLINE MonoClass* GetNative() const + { + return _monoClass; + } #endif /// @@ -142,19 +145,21 @@ public: /// True if this class is a sub class of the specified class. bool IsSubClassOf(const MClass* klass) const; +#if USE_MONO /// /// Checks if this class is a sub class of the specified class (including any derived types). /// /// The Mono class. /// True if this class is a sub class of the specified class. bool IsSubClassOf(MonoClass* monoClass) const; +#endif /// /// Checks is the provided object instance of this class' type. /// /// The object to check. /// True if object is an instance the this class. - bool IsInstanceOfType(MonoObject* object) const; + bool IsInstanceOfType(MObject* object) const; /// /// Returns the size of an instance of this class, in bytes. @@ -217,14 +222,6 @@ public: /// The event object. MEvent* GetEvent(const char* name); - /// - /// Adds event with the specified name to the cache. - /// - /// The event name. - /// The event Mono object. - /// The event. - MEvent* AddEvent(const char* name, MonoEvent* event); - /// /// Returns all events belonging to this class. /// @@ -257,7 +254,7 @@ public: /// Creates a new instance of this class and constructs it. /// /// The created managed object. - MonoObject* CreateInstance() const; + MObject* CreateInstance() const; /// /// Creates a new instance of this class and then constructs it using the constructor with the specified number of parameters. @@ -265,7 +262,7 @@ public: /// The array containing pointers to constructor parameters. Array length must be equal to number of parameters. /// The number of parameters the constructor accepts. /// The created managed object. - MonoObject* CreateInstance(void** params, uint32 numParams); + MObject* CreateInstance(void** params, uint32 numParams); public: @@ -287,11 +284,11 @@ public: /// /// The attribute class to take. /// The attribute object. - MonoObject* GetAttribute(MClass* monoClass); + MObject* GetAttribute(MClass* monoClass); /// /// Returns an instance of all attributes connected with given class. Returns null if the class doesn't have any attributes. /// /// The array of attribute objects. - const Array& GetAttributes(); + const Array& GetAttributes(); }; diff --git a/Source/Engine/Scripting/ManagedCLR/MCore.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MCore.cpp similarity index 98% rename from Source/Engine/Scripting/ManagedCLR/MCore.Mono.cpp rename to Source/Engine/Scripting/ManagedCLR/MCore.cpp index d0b43464b..6c71a5879 100644 --- a/Source/Engine/Scripting/ManagedCLR/MCore.Mono.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MCore.cpp @@ -1,9 +1,6 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "MCore.h" - -#if USE_MONO - #include "MDomain.h" #include "MClass.h" #include "Engine/Core/Log.h" @@ -16,6 +13,7 @@ #include "Engine/Platform/Thread.h" #include "Engine/Scripting/MException.h" #include "Engine/Profiler/ProfilerCPU.h" +#if USE_MONO #ifdef USE_MONO_AOT_MODULE #include "Engine/Core/Types/TimeSpan.h" #endif @@ -33,15 +31,24 @@ #if !USE_MONO_DYNAMIC_LIB #include #endif +#endif #ifdef USE_MONO_AOT_MODULE void* MonoAotModuleHandle = nullptr; #endif -MCore::MCore() - : _rootDomain(nullptr) - , _activeDomain(nullptr) +MDomain* MRootDomain = nullptr; +MDomain* MActiveDomain = nullptr; +Array> MDomains; + +MDomain* MCore::GetRootDomain() { + return MRootDomain; +} + +MDomain* MCore::GetActiveDomain() +{ + return MActiveDomain; } MDomain* MCore::CreateDomain(const MString& domainName) @@ -51,50 +58,56 @@ MDomain* MCore::CreateDomain(const MString& domainName) return nullptr; #endif - for (int32 i = 0; i < _domains.Count(); i++) + for (int32 i = 0; i < MDomains.Count(); i++) { - if (_domains[i]->GetName() == domainName) - return _domains[i]; + if (MDomains[i]->GetName() == domainName) + return MDomains[i]; } - + + auto domain = New(domainName); +#if USE_MONO const auto monoDomain = mono_domain_create_appdomain((char*)domainName.Get(), nullptr); #if MONO_DEBUG_ENABLE mono_debug_domain_create(monoDomain); #endif ASSERT(monoDomain); - auto domain = New(domainName, monoDomain); - _domains.Add(domain); + domain->_monoDomain = monoDomain; +#endif + MDomains.Add(domain); return domain; } void MCore::UnloadDomain(const MString& domainName) { int32 i = 0; - for (; i < _domains.Count(); i++) + for (; i < MDomains.Count(); i++) { - if (_domains[i]->GetName() == domainName) + if (MDomains[i]->GetName() == domainName) break; } - if (i == _domains.Count()) + if (i == MDomains.Count()) return; - auto domain = _domains[i]; + auto domain = MDomains[i]; +#if USE_MONO #if MONO_DEBUG_ENABLE //mono_debug_domain_unload(domain->GetNative()); #endif - //mono_domain_finalize(_monoScriptsDomain, 2000); - - MonoObject* exception = nullptr; + //mono_domain_finalize(domain->GetNative(), 2000); + MObject* exception = nullptr; mono_domain_try_unload(domain->GetNative(), &exception); if (exception) { MException ex(exception); ex.Log(LogType::Fatal, TEXT("Scripting::Release")); } +#endif Delete(domain); - _domains.RemoveAtKeepOrder(i); + MDomains.RemoveAtKeepOrder(i); } +#if USE_MONO + #if 0 void* MonoMalloc(size_t size) @@ -254,7 +267,7 @@ void OnLogCallback(const char* logDomain, const char* logLevel, const char* mess if (currentDomain.IsEmpty()) { - auto domain = MCore::Instance()->GetActiveDomain(); + auto domain = MCore::GetActiveDomain(); if (domain != nullptr) { currentDomain = domain->GetName().Get(); @@ -443,7 +456,7 @@ bool MCore::LoadEngine() #endif // Connects to mono engine callback system - mono_trace_set_log_handler(OnLogCallback, this); + mono_trace_set_log_handler(OnLogCallback, nullptr); mono_trace_set_print_handler(OnPrintCallback); mono_trace_set_printerr_handler(OnPrintErrorCallback); } @@ -505,7 +518,7 @@ bool MCore::LoadEngine() } #endif - // Init Mono +// Init Mono #if PLATFORM_ANDROID const char* monoVersion = "mobile"; #else @@ -513,8 +526,9 @@ bool MCore::LoadEngine() #endif auto monoRootDomain = mono_jit_init_version("Flax", monoVersion); ASSERT(monoRootDomain); - _rootDomain = New("Root", monoRootDomain); - _domains.Add(_rootDomain); + MRootDomain = New("Root"); + MRootDomain->_monoDomain = monoRootDomain; + MDomains.Add(MRootDomain); auto exePath = Platform::GetExecutableFilePath(); auto configDir = StringUtils::GetDirectoryName(exePath).ToStringAnsi(); @@ -553,29 +567,29 @@ void MCore::UnloadEngine() Thread::ThreadExiting.Unbind(); // Only root domain should be alive at this point - for (auto domain : _domains) + for (auto domain : MDomains) { - if (domain != _rootDomain) + if (domain != MRootDomain) Delete(domain); } - _domains.Clear(); + MDomains.Clear(); - if (_rootDomain) + if (MRootDomain) { #if PLATFORM_WINDOWS && USE_EDITOR // TODO: reduce issues with hot-reloading C# DLLs because sometimes it crashes on exit __try #endif { - mono_jit_cleanup(_rootDomain->GetNative()); + mono_jit_cleanup(MRootDomain->GetNative()); } #if PLATFORM_WINDOWS && USE_EDITOR __except (MonoHackSehExceptionHandler(nullptr)) { } #endif - Delete(_rootDomain); - _rootDomain = nullptr; + Delete(MRootDomain); + MRootDomain = nullptr; } #ifdef USE_MONO_AOT_MODULE @@ -591,39 +605,65 @@ void MCore::UnloadEngine() #endif } +#else + +bool MCore::LoadEngine() +{ + MRootDomain = New("Root"); + MDomains.Add(MRootDomain); + return false; +} + +void MCore::UnloadEngine() +{ + MDomains.ClearDelete(); + MRootDomain = nullptr; +} + +#endif + void MCore::AttachThread() { +#if USE_MONO if (!IsInMainThread() && !mono_domain_get()) { - const auto domain = Instance()->GetActiveDomain(); + const auto domain = GetActiveDomain(); ASSERT(domain); mono_thread_attach(domain->GetNative()); } +#endif } void MCore::ExitThread() { +#if USE_MONO if (!IsInMainThread() && mono_domain_get()) { LOG(Info, "Thread 0x{0:x} exits the managed runtime", Platform::GetCurrentThreadID()); mono_thread_exit(); } +#endif } void MCore::GC::Collect() { +#if USE_MONO PROFILE_CPU(); mono_gc_collect(mono_gc_max_generation()); +#endif } void MCore::GC::Collect(int32 generation) { +#if USE_MONO PROFILE_CPU(); mono_gc_collect(generation); +#endif } void MCore::GC::WaitForPendingFinalizers() { +#if USE_MONO PROFILE_CPU(); if (mono_gc_pending_finalizers()) { @@ -633,9 +673,10 @@ void MCore::GC::WaitForPendingFinalizers() Platform::Sleep(1); } while (mono_gc_pending_finalizers()); } +#endif } -#if PLATFORM_WIN32 && !USE_MONO_DYNAMIC_LIB +#if USE_MONO && PLATFORM_WIN32 && !USE_MONO_DYNAMIC_LIB // Export Mono functions #pragma comment(linker, "/export:mono_add_internal_call") @@ -2109,5 +2150,3 @@ void MCore::GC::WaitForPendingFinalizers() #pragma comment(linker, "/export:mono_jit_info_get_code_size") #endif - -#endif diff --git a/Source/Engine/Scripting/ManagedCLR/MCore.h b/Source/Engine/Scripting/ManagedCLR/MCore.h index 4c6380d0f..27aa24655 100644 --- a/Source/Engine/Scripting/ManagedCLR/MCore.h +++ b/Source/Engine/Scripting/ManagedCLR/MCore.h @@ -2,63 +2,37 @@ #pragma once -#include "Engine/Core/Types/String.h" -#include "Engine/Core/Collections/Array.h" -#include "Engine/Core/Singleton.h" #include "MTypes.h" /// /// Main handler for CLR Engine. /// -class FLAXENGINE_API MCore : public Singleton +class FLAXENGINE_API MCore { - friend MDomain; - -private: - - MDomain* _rootDomain; - MDomain* _activeDomain; - Array> _domains; - public: /// - /// Initializes a new instance of the class. + /// Gets the root domain. /// - MCore(); + static MDomain* GetRootDomain(); -public: + /// + /// Gets the currently active domain. + /// + static MDomain* GetActiveDomain(); /// /// Creates an new empty domain. /// /// The domain name to create. /// The domain object. - MDomain* CreateDomain(const MString& domainName); + static MDomain* CreateDomain(const MString& domainName); /// /// Unloads the domain. /// /// The domain name to remove. - void UnloadDomain(const MString& domainName); - - /// - /// Gets the root domain. - /// - /// The root domain. - FORCE_INLINE MDomain* GetRootDomain() const - { - return _rootDomain; - } - - /// - /// Gets the currently active domain. - /// - /// The current domain. - FORCE_INLINE MDomain* GetActiveDomain() const - { - return _activeDomain; - } + static void UnloadDomain(const MString& domainName); public: @@ -66,12 +40,12 @@ public: /// Initialize CLR Engine /// /// True if failed, otherwise false. - bool LoadEngine(); + static bool LoadEngine(); /// /// Unload CLR Engine /// - void UnloadEngine(); + static void UnloadEngine(); /// /// Attaches CLR runtime to the current thread. Use it to allow invoking managed runtime from native threads. diff --git a/Source/Engine/Scripting/ManagedCLR/MDomain.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MDomain.cpp similarity index 82% rename from Source/Engine/Scripting/ManagedCLR/MDomain.Mono.cpp rename to Source/Engine/Scripting/ManagedCLR/MDomain.cpp index 7f8119e88..b684352ee 100644 --- a/Source/Engine/Scripting/ManagedCLR/MDomain.Mono.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MDomain.cpp @@ -1,38 +1,31 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "MDomain.h" - -#if USE_MONO - #include "MCore.h" #include "MAssembly.h" #include "Engine/Threading/Threading.h" #include "Engine/Core/Log.h" #include "Engine/Debug/Exceptions/ArgumentException.h" #include "Engine/Debug/Exceptions/Exceptions.h" +#if USE_MONO #include +#endif -MDomain::MDomain(const MString& domainName, MonoDomain* monoDomain) - : _monoDomain(monoDomain) - , _domainName(domainName) - , _coreInstance(MCore::Instance()) -{ -} +extern MDomain* MActiveDomain; -MonoDomain* MDomain::GetNative() const +MDomain::MDomain(const MString& domainName) + : _domainName(domainName) { - return _monoDomain; } bool MDomain::SetCurrentDomain(bool force) { - ASSERT(_monoDomain); - const auto monoBool = mono_domain_set(_monoDomain, force) != 0; - if (monoBool) - { - _coreInstance->_activeDomain = this; - } - return monoBool; +#if USE_MONO + if (mono_domain_set(_monoDomain, force) == 0) + return false; +#endif + MActiveDomain = this; + return true; } MAssembly* MDomain::CreateEmptyAssembly(const MString& assemblyName, const MAssemblyOptions options) @@ -72,10 +65,12 @@ MAssembly* MDomain::GetAssembly(const MString& assemblyName) const void MDomain::Dispatch() const { +#if USE_MONO if (!IsInMainThread()) { mono_thread_attach(_monoDomain); } +#endif } MClass* MDomain::FindClass(const StringAnsiView& fullname) const @@ -90,5 +85,3 @@ MClass* MDomain::FindClass(const StringAnsiView& fullname) const } return nullptr; } - -#endif diff --git a/Source/Engine/Scripting/ManagedCLR/MDomain.h b/Source/Engine/Scripting/ManagedCLR/MDomain.h index d83669832..03cfad2fe 100644 --- a/Source/Engine/Scripting/ManagedCLR/MDomain.h +++ b/Source/Engine/Scripting/ManagedCLR/MDomain.h @@ -17,7 +17,6 @@ class FLAXENGINE_API MDomain { friend MCore; friend MAssembly; - public: typedef Dictionary AssembliesDictionary; @@ -27,38 +26,43 @@ private: #if USE_MONO MonoDomain* _monoDomain; #endif - MString _domainName; AssembliesDictionary _assemblies; - MCore* _coreInstance; + +public: + + MDomain(const MString& domainName); public: #if USE_MONO - MDomain(const MString& domainName, MonoDomain* monoDomain); -#endif - -public: - -#if USE_MONO - /// - /// Gets native domain class + /// Gets native domain class. /// - /// The native domain. - MonoDomain* GetNative() const; - + FORCE_INLINE MonoDomain* GetNative() const + { + return _monoDomain; + } #endif /// /// Gets current domain name /// - /// The name. FORCE_INLINE const MString& GetName() const { return _domainName; } + /// + /// Gets the current domain assemblies. + /// + FORCE_INLINE const AssembliesDictionary& GetAssemblies() const + { + return _assemblies; + } + +public: + /// /// Create assembly container from current domain /// @@ -73,15 +77,6 @@ public: /// Assembly name void RemoveAssembly(const MString& assemblyName); - /// - /// Gets the current domain assemblies. - /// - /// The assemblies. - FORCE_INLINE const AssembliesDictionary& GetAssemblies() const - { - return _assemblies; - } - /// /// Gets current domain assembly. /// diff --git a/Source/Engine/Scripting/ManagedCLR/MEvent.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MEvent.cpp similarity index 91% rename from Source/Engine/Scripting/ManagedCLR/MEvent.Mono.cpp rename to Source/Engine/Scripting/ManagedCLR/MEvent.cpp index ad61e1f01..9dfe21ecb 100644 --- a/Source/Engine/Scripting/ManagedCLR/MEvent.Mono.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MEvent.cpp @@ -1,11 +1,9 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "MEvent.h" - -#if USE_MONO - #include "MType.h" #include "MClass.h" +#if USE_MONO #include MEvent::MEvent(MonoEvent* monoEvent, const char* name, MClass* parentClass) @@ -24,13 +22,14 @@ MEvent::MEvent(MonoEvent* monoEvent, const char* name, MClass* parentClass) #endif } +#endif + MType MEvent::GetType() { if (GetAddMethod() != nullptr) return GetAddMethod()->GetReturnType(); if (GetRemoveMethod() != nullptr) return GetRemoveMethod()->GetReturnType(); - CRASH; return MType(); } @@ -40,12 +39,14 @@ MMethod* MEvent::GetAddMethod() return nullptr; if (_addMethod == nullptr) { +#if USE_MONO auto addMonoMethod = mono_event_get_add_method(_monoEvent); if (addMonoMethod != nullptr) { _hasAddMonoMethod = true; return _addMethod = New(addMonoMethod, _parentClass); } +#endif } return _addMethod; } @@ -56,19 +57,21 @@ MMethod* MEvent::GetRemoveMethod() return nullptr; if (_removeMethod == nullptr) { +#if USE_MONO auto removeMonoMethod = mono_event_get_remove_method(_monoEvent); if (removeMonoMethod) { _hasRemoveMonoMethod = true; return _removeMethod = New(removeMonoMethod, _parentClass); } - return nullptr; +#endif } return _removeMethod; } bool MEvent::HasAttribute(MClass* monoClass) const { +#if USE_MONO MonoClass* parentClass = mono_event_get_parent(_monoEvent); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_event(parentClass, _monoEvent); if (attrInfo == nullptr) @@ -77,10 +80,14 @@ bool MEvent::HasAttribute(MClass* monoClass) const const bool hasAttr = mono_custom_attrs_has_attr(attrInfo, monoClass->GetNative()) != 0; mono_custom_attrs_free(attrInfo); return hasAttr; +#else + return false; +#endif } bool MEvent::HasAttribute() const { +#if USE_MONO MonoClass* parentClass = mono_event_get_parent(_monoEvent); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_event(parentClass, _monoEvent); if (attrInfo == nullptr) @@ -93,10 +100,14 @@ bool MEvent::HasAttribute() const } mono_custom_attrs_free(attrInfo); return false; +#else + return false; +#endif } -MonoObject* MEvent::GetAttribute(MClass* monoClass) const +MObject* MEvent::GetAttribute(MClass* monoClass) const { +#if USE_MONO MonoClass* parentClass = mono_event_get_parent(_monoEvent); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_event(parentClass, _monoEvent); if (attrInfo == nullptr) @@ -105,14 +116,18 @@ MonoObject* MEvent::GetAttribute(MClass* monoClass) const MonoObject* foundAttr = mono_custom_attrs_get_attr(attrInfo, monoClass->GetNative()); mono_custom_attrs_free(attrInfo); return foundAttr; +#else + return false; +#endif } -const Array& MEvent::GetAttributes() +const Array& MEvent::GetAttributes() { if (_hasCachedAttributes) return _attributes; _hasCachedAttributes = true; +#if USE_MONO MonoClass* parentClass = mono_event_get_parent(_monoEvent); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_event(parentClass, _monoEvent); if (attrInfo == nullptr) @@ -122,9 +137,8 @@ const Array& MEvent::GetAttributes() const auto length = (uint32)mono_array_length(monoAttributesArray); _attributes.Resize(length); for (uint32 i = 0; i < length; i++) - _attributes[i] = mono_array_get(monoAttributesArray, MonoObject*, i); + _attributes[i] = mono_array_get(monoAttributesArray, MonoObject *, i); mono_custom_attrs_free(attrInfo); +#endif return _attributes; } - -#endif diff --git a/Source/Engine/Scripting/ManagedCLR/MEvent.h b/Source/Engine/Scripting/ManagedCLR/MEvent.h index df1914176..4e431f8f9 100644 --- a/Source/Engine/Scripting/ManagedCLR/MEvent.h +++ b/Source/Engine/Scripting/ManagedCLR/MEvent.h @@ -23,12 +23,12 @@ protected: MString _name; - Array _attributes; - int32 _hasCachedAttributes : 1; int32 _hasAddMonoMethod : 1; int32 _hasRemoveMonoMethod : 1; + Array _attributes; + public: #if USE_MONO @@ -40,7 +40,6 @@ public: /// /// Gets the event name. /// - /// The name. FORCE_INLINE const MString& GetName() const { return _name; @@ -49,7 +48,6 @@ public: /// /// Returns the parent class that this method is contained with. /// - /// The parent class. FORCE_INLINE MClass* GetParentClass() const { return _parentClass; @@ -58,25 +56,21 @@ public: /// /// Gets the event type class. /// - /// The type class. MType GetType(); /// /// Gets the event add method. /// - /// The method object. MMethod* GetAddMethod(); /// /// Gets the event remove method. /// - /// The method object. MMethod* GetRemoveMethod(); /// /// Gets event visibility in the class. /// - /// The event visibility. FORCE_INLINE MVisibility GetVisibility() { return GetAddMethod()->GetVisibility(); @@ -85,23 +79,19 @@ public: /// /// Returns true if event is static. /// - /// True if is static, otherwise false. FORCE_INLINE bool IsStatic() { return GetAddMethod()->IsStatic(); } #if USE_MONO - /// /// Gets the Mono event handle. /// - /// The Mono event. FORCE_INLINE MonoEvent* GetNative() const { return _monoEvent; } - #endif public: @@ -124,11 +114,11 @@ public: /// /// The attribute class to take. /// The attribute object. - MonoObject* GetAttribute(MClass* monoClass) const; + MObject* GetAttribute(MClass* monoClass) const; /// /// Returns an instance of all attributes connected with given event. Returns null if the event doesn't have any attributes. /// /// The array of attribute objects. - const Array& GetAttributes(); + const Array& GetAttributes(); }; diff --git a/Source/Engine/Scripting/ManagedCLR/MField.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MField.cpp similarity index 86% rename from Source/Engine/Scripting/ManagedCLR/MField.Mono.cpp rename to Source/Engine/Scripting/ManagedCLR/MField.cpp index cea174462..ced79dda3 100644 --- a/Source/Engine/Scripting/ManagedCLR/MField.Mono.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MField.cpp @@ -1,11 +1,9 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "MField.h" - -#if USE_MONO - #include "MType.h" #include "MClass.h" +#if USE_MONO #include #include @@ -48,33 +46,52 @@ MField::MField(MonoClassField* monoField, const char* name, MClass* parentClass) _isStatic = (flags & MONO_FIELD_ATTR_STATIC) != 0; } +#endif + MType MField::GetType() const { +#if USE_MONO return MType(_monoType); +#else + return MType(); +#endif } int32 MField::GetOffset() const { +#if USE_MONO return mono_field_get_offset(_monoField) - sizeof(MonoObject); +#else + return 0; +#endif } -void MField::GetValue(MonoObject* instance, void* result) const +void MField::GetValue(MObject* instance, void* result) const { +#if USE_MONO mono_field_get_value(instance, _monoField, result); +#endif } -MonoObject* MField::GetValueBoxed(MonoObject* instance) const +MObject* MField::GetValueBoxed(MObject* instance) const { +#if USE_MONO return mono_field_get_value_object(mono_domain_get(), _monoField, instance); +#else + return nullptr; +#endif } -void MField::SetValue(MonoObject* instance, void* value) const +void MField::SetValue(MObject* instance, void* value) const { +#if USE_MONO mono_field_set_value(instance, _monoField, value); +#endif } bool MField::HasAttribute(MClass* monoClass) const { +#if USE_MONO MonoClass* parentClass = mono_field_get_parent(_monoField); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_field(parentClass, _monoField); if (attrInfo == nullptr) @@ -83,10 +100,14 @@ bool MField::HasAttribute(MClass* monoClass) const const bool hasAttr = mono_custom_attrs_has_attr(attrInfo, monoClass->GetNative()) != 0; mono_custom_attrs_free(attrInfo); return hasAttr; +#else + return false; +#endif } bool MField::HasAttribute() const { +#if USE_MONO MonoClass* parentClass = mono_field_get_parent(_monoField); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_field(parentClass, _monoField); if (attrInfo == nullptr) @@ -98,11 +119,13 @@ bool MField::HasAttribute() const return true; } mono_custom_attrs_free(attrInfo); +#endif return false; } -MonoObject* MField::GetAttribute(MClass* monoClass) const +MObject* MField::GetAttribute(MClass* monoClass) const { +#if USE_MONO MonoClass* parentClass = mono_field_get_parent(_monoField); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_field(parentClass, _monoField); if (attrInfo == nullptr) @@ -111,14 +134,18 @@ MonoObject* MField::GetAttribute(MClass* monoClass) const MonoObject* foundAttr = mono_custom_attrs_get_attr(attrInfo, monoClass->GetNative()); mono_custom_attrs_free(attrInfo); return foundAttr; +#else + return nullptr; +#endif } -const Array& MField::GetAttributes() +const Array& MField::GetAttributes() { if (_hasCachedAttributes) return _attributes; _hasCachedAttributes = true; +#if USE_MONO MonoClass* parentClass = mono_field_get_parent(_monoField); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_field(parentClass, _monoField); if (attrInfo == nullptr) @@ -130,7 +157,6 @@ const Array& MField::GetAttributes() for (uint32 i = 0; i < length; i++) _attributes[i] = mono_array_get(monoAttributesArray, MonoObject*, i); mono_custom_attrs_free(attrInfo); +#endif return _attributes; } - -#endif diff --git a/Source/Engine/Scripting/ManagedCLR/MField.h b/Source/Engine/Scripting/ManagedCLR/MField.h index 49b51ca9f..d5e49910b 100644 --- a/Source/Engine/Scripting/ManagedCLR/MField.h +++ b/Source/Engine/Scripting/ManagedCLR/MField.h @@ -20,15 +20,15 @@ protected: #endif MClass* _parentClass; - MString _name; - MVisibility _visibility; - Array _attributes; + MVisibility _visibility; int32 _hasCachedAttributes : 1; int32 _isStatic : 1; + Array _attributes; + public: #if USE_MONO @@ -40,7 +40,6 @@ public: /// /// Gets field name. /// - /// The field name. FORCE_INLINE const MString& GetName() const { return _name; @@ -49,7 +48,6 @@ public: /// /// Returns the parent class that this method is contained with. /// - /// The parent class. FORCE_INLINE MClass* GetParentClass() const { return _parentClass; @@ -58,19 +56,16 @@ public: /// /// Gets field type class. /// - /// The field type. MType GetType() const; /// /// Gets the field offset (in bytes) from the start of the parent object. /// - /// The field offset in bytes. int32 GetOffset() const; /// /// Gets field visibility in the class. /// - /// The field visibility. FORCE_INLINE MVisibility GetVisibility() const { return _visibility; @@ -79,23 +74,19 @@ public: /// /// Returns true if field is static. /// - /// True if is static, otherwise false. FORCE_INLINE bool IsStatic() const { return _isStatic != 0; } #if USE_MONO - /// /// Gets mono field handle. /// - /// The Mono field object. FORCE_INLINE MonoClassField* GetNative() const { return _monoField; } - #endif public: @@ -104,28 +95,28 @@ public: /// Retrieves value currently set in the field on the specified object instance. If field is static object instance can be null. /// /// - /// Value will be a pointer to raw data type for value types (for example int, float), and a MonoObject* for reference types. + /// Value will be a pointer to raw data type for value types (for example int, float), and a MObject* for reference types. /// /// The object of given type to get value from. /// The return value of undefined type. - void GetValue(MonoObject* instance, void* result) const; + void GetValue(MObject* instance, void* result) const; /// /// Retrieves value currently set in the field on the specified object instance. If field is static object instance can be null. If returned value is a value type it will be boxed. /// /// The object of given type to get value from. /// The boxed value object. - MonoObject* GetValueBoxed(MonoObject* instance) const; + MObject* GetValueBoxed(MObject* instance) const; /// /// Sets a value for the field on the specified object instance. If field is static object instance can be null. /// /// - /// Value should be a pointer to raw data type for value types (for example int, float), and a MonoObject* for reference types. + /// Value should be a pointer to raw data type for value types (for example int, float), and a MObject* for reference types. /// /// The object of given type to set value to. /// Th value of undefined type. - void SetValue(MonoObject* instance, void* value) const; + void SetValue(MObject* instance, void* value) const; public: @@ -147,11 +138,11 @@ public: /// /// The attribute class to take. /// The attribute object. - MonoObject* GetAttribute(MClass* monoClass) const; + MObject* GetAttribute(MClass* monoClass) const; /// /// Returns an instance of all attributes connected with given field. Returns null if the field doesn't have any attributes. /// /// The array of attribute objects. - const Array& GetAttributes(); + const Array& GetAttributes(); }; diff --git a/Source/Engine/Scripting/ManagedCLR/MMethod.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MMethod.cpp similarity index 88% rename from Source/Engine/Scripting/ManagedCLR/MMethod.Mono.cpp rename to Source/Engine/Scripting/ManagedCLR/MMethod.cpp index 6abff601d..2b2246e94 100644 --- a/Source/Engine/Scripting/ManagedCLR/MMethod.Mono.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MMethod.cpp @@ -1,12 +1,10 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "MMethod.h" - -#if USE_MONO - #include "MType.h" #include "MClass.h" #include "Engine/Profiler/ProfilerCPU.h" +#if USE_MONO #include #include @@ -68,17 +66,27 @@ MMethod::MMethod(MonoMethod* monoMethod, const char* name, MClass* parentClass) #endif } -MonoObject* MMethod::Invoke(void* instance, void** params, MonoObject** exception) const +#endif + +MObject* MMethod::Invoke(void* instance, void** params, MObject** exception) const { +#if USE_MONO PROFILE_CPU_SRC_LOC(ProfilerData); return mono_runtime_invoke(_monoMethod, instance, params, exception); +#else + return nullptr; +#endif } -MonoObject* MMethod::InvokeVirtual(MonoObject* instance, void** params, MonoObject** exception) const +MObject* MMethod::InvokeVirtual(MObject* instance, void** params, MObject** exception) const { +#if USE_MONO PROFILE_CPU_SRC_LOC(ProfilerData); MonoMethod* virtualMethod = mono_object_get_virtual_method(instance, _monoMethod); return mono_runtime_invoke(virtualMethod, instance, params, exception); +#else + return nullptr; +#endif } #if !USE_MONO_AOT @@ -87,7 +95,9 @@ void* MMethod::GetThunk() { if (!_cachedThunk) { +#if USE_MONO _cachedThunk = mono_method_get_unmanaged_thunk(_monoMethod); +#endif } return _cachedThunk; } @@ -96,35 +106,52 @@ void* MMethod::GetThunk() MType MMethod::GetReturnType() const { +#if USE_MONO MonoMethodSignature* sig = mono_method_signature(_monoMethod); MonoType* returnType = mono_signature_get_return_type(sig); return MType(returnType); +#else + return MType(); +#endif } int32 MMethod::GetParametersCount() const { +#if USE_MONO MonoMethodSignature* sig = mono_method_signature(_monoMethod); return mono_signature_get_param_count(sig); +#else + return 0; +#endif } MType MMethod::GetParameterType(int32 paramIdx) const { +#if USE_MONO MonoMethodSignature* sig = mono_method_signature(_monoMethod); ASSERT_LOW_LAYER(paramIdx >= 0 && paramIdx < (int32)mono_signature_get_param_count(sig)); void* it = nullptr; mono_signature_get_params(sig, &it); return MType(((MonoType**)it)[paramIdx]); +#else + return MType(); +#endif } bool MMethod::GetParameterIsOut(int32 paramIdx) const { +#if USE_MONO MonoMethodSignature* sig = mono_method_signature(_monoMethod); ASSERT_LOW_LAYER(paramIdx >= 0 && paramIdx < (int32)mono_signature_get_param_count(sig)); return mono_signature_param_is_out(sig, paramIdx) != 0; +#else + return false; +#endif } bool MMethod::HasAttribute(MClass* monoClass) const { +#if USE_MONO MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_method(_monoMethod); if (attrInfo == nullptr) return false; @@ -132,10 +159,14 @@ bool MMethod::HasAttribute(MClass* monoClass) const const bool hasAttr = mono_custom_attrs_has_attr(attrInfo, monoClass->GetNative()) != 0; mono_custom_attrs_free(attrInfo); return hasAttr; +#else + return false; +#endif } bool MMethod::HasAttribute() const { +#if USE_MONO MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_method(_monoMethod); if (attrInfo == nullptr) return false; @@ -146,11 +177,13 @@ bool MMethod::HasAttribute() const return true; } mono_custom_attrs_free(attrInfo); +#endif return false; } -MonoObject* MMethod::GetAttribute(MClass* monoClass) const +MObject* MMethod::GetAttribute(MClass* monoClass) const { +#if USE_MONO MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_method(_monoMethod); if (attrInfo == nullptr) return nullptr; @@ -158,14 +191,18 @@ MonoObject* MMethod::GetAttribute(MClass* monoClass) const MonoObject* foundAttr = mono_custom_attrs_get_attr(attrInfo, monoClass->GetNative()); mono_custom_attrs_free(attrInfo); return foundAttr; +#else + return false; +#endif } -const Array& MMethod::GetAttributes() +const Array& MMethod::GetAttributes() { if (_hasCachedAttributes) return _attributes; _hasCachedAttributes = true; +#if USE_MONO MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_method(_monoMethod); if (attrInfo == nullptr) return _attributes; @@ -176,7 +213,6 @@ const Array& MMethod::GetAttributes() for (uint32 i = 0; i < length; i++) _attributes[i] = mono_array_get(monoAttributesArray, MonoObject*, i); mono_custom_attrs_free(attrInfo); +#endif return _attributes; } - -#endif diff --git a/Source/Engine/Scripting/ManagedCLR/MMethod.h b/Source/Engine/Scripting/ManagedCLR/MMethod.h index 46320013f..a2d27305b 100644 --- a/Source/Engine/Scripting/ManagedCLR/MMethod.h +++ b/Source/Engine/Scripting/ManagedCLR/MMethod.h @@ -29,11 +29,11 @@ protected: void* _cachedThunk = nullptr; #endif - Array _attributes; - int32 _hasCachedAttributes : 1; int32 _isStatic : 1; + Array _attributes; + public: #if USE_MONO @@ -48,8 +48,6 @@ public: SourceLocationData ProfilerData; #endif -#if USE_MONO - /// /// Invokes the method on the provided object instance. This does not respect polymorphism and will invoke the exact method of the class this object was retrieved from.Use invokeVirtual() if you need polymorphism. /// @@ -59,10 +57,10 @@ public: /// Instance of the object to invoke the method on. Can be null for static methods. /// Array of parameters to pass to the method. Caller must ensure they match method /// parameter count and type.For value types parameters should be pointers to the - /// values and for reference types they should be pointers to MonoObject. + /// values and for reference types they should be pointers to MObject. /// An optional pointer to the exception value to store exception object reference. /// A boxed return value, or null if method has no return value. - MonoObject* Invoke(void* instance, void** params, MonoObject** exception) const; + MObject* Invoke(void* instance, void** params, MObject** exception) const; /// /// Invokes the method on the provided object instance. If the instance has an override of this method it will be called. @@ -74,16 +72,13 @@ public: /// /// Array of parameters to pass to the method. Caller must ensure they match method /// parameter count and type. For value types parameters should be pointers to the - /// values and for reference types they should be pointers to MonoObject. + /// values and for reference types they should be pointers to MObject. /// /// An optional pointer to the exception value to store exception object reference. /// A boxed return value, or null if method has no return value. - MonoObject* InvokeVirtual(MonoObject* instance, void** params, MonoObject** exception) const; - -#endif + MObject* InvokeVirtual(MObject* instance, void** params, MObject** exception) const; #if !USE_MONO_AOT - /// /// Gets a thunk for this method. A thunk is a C++ like function pointer that you can use for calling the method. /// @@ -93,7 +88,6 @@ public: /// /// The method thunk pointer. void* GetThunk(); - #endif /// @@ -153,7 +147,6 @@ public: } #if USE_MONO - /// /// Gets the Mono method handle. /// @@ -161,7 +154,6 @@ public: { return _monoMethod; } - #endif public: @@ -184,11 +176,11 @@ public: /// /// The attribute Class to take. /// The attribute object. - MonoObject* GetAttribute(MClass* monoClass) const; + MObject* GetAttribute(MClass* monoClass) const; /// /// Returns an instance of all attributes connected with given method. Returns null if the method doesn't have any attributes. /// /// The array of attribute objects. - const Array& GetAttributes(); + const Array& GetAttributes(); }; diff --git a/Source/Engine/Scripting/ManagedCLR/MProperty.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MProperty.cpp similarity index 89% rename from Source/Engine/Scripting/ManagedCLR/MProperty.Mono.cpp rename to Source/Engine/Scripting/ManagedCLR/MProperty.cpp index 17d0cd3de..23368a918 100644 --- a/Source/Engine/Scripting/ManagedCLR/MProperty.Mono.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MProperty.cpp @@ -1,13 +1,11 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "MProperty.h" - -#if USE_MONO - #include "Engine/Core/Math/Math.h" #include "MMethod.h" #include "MClass.h" #include "MType.h" +#if USE_MONO #include MProperty::MProperty(MonoProperty* monoProperty, const char* name, MClass* parentClass) @@ -29,6 +27,8 @@ MProperty::MProperty(MonoProperty* monoProperty, const char* name, MClass* paren GetSetMethod(); } +#endif + MProperty::~MProperty() { if (_getMethod) @@ -48,18 +48,17 @@ MMethod* MProperty::GetGetMethod() { if (!_hasGetMethod) return nullptr; - if (_getMethod == nullptr) { +#if USE_MONO auto method = mono_property_get_get_method(_monoProperty); if (method != nullptr) { _hasGetMethod = true; return _getMethod = New(method, _parentClass); } - return nullptr; +#endif } - return _getMethod; } @@ -67,18 +66,17 @@ MMethod* MProperty::GetSetMethod() { if (!_hasSetMethod) return nullptr; - if (_setMethod == nullptr) { +#if USE_MONO auto method = mono_property_get_set_method(_monoProperty); if (method != nullptr) { _hasSetMethod = true; return _setMethod = New(method, _parentClass); } - return nullptr; +#endif } - return _setMethod; } @@ -112,20 +110,27 @@ bool MProperty::IsStatic() return false; } -MonoObject* MProperty::GetValue(MonoObject* instance, MonoObject** exception) +MObject* MProperty::GetValue(MObject* instance, MObject** exception) { +#if USE_MONO return mono_property_get_value(_monoProperty, instance, nullptr, exception); +#else + return nullptr; +#endif } -void MProperty::SetValue(MonoObject* instance, void* value, MonoObject** exception) +void MProperty::SetValue(MObject* instance, void* value, MObject** exception) { +#if USE_MONO void* params[1]; params[0] = value; mono_property_set_value(_monoProperty, instance, params, exception); +#endif } bool MProperty::HasAttribute(MClass* monoClass) const { +#if USE_MONO MonoClass* parentClass = mono_property_get_parent(_monoProperty); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_property(parentClass, _monoProperty); if (attrInfo == nullptr) @@ -134,10 +139,14 @@ bool MProperty::HasAttribute(MClass* monoClass) const const bool hasAttr = mono_custom_attrs_has_attr(attrInfo, monoClass->GetNative()) != 0; mono_custom_attrs_free(attrInfo); return hasAttr; +#else + return false; +#endif } bool MProperty::HasAttribute() const { +#if USE_MONO MonoClass* parentClass = mono_property_get_parent(_monoProperty); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_property(parentClass, _monoProperty); if (attrInfo == nullptr) @@ -150,10 +159,14 @@ bool MProperty::HasAttribute() const } mono_custom_attrs_free(attrInfo); return false; +#else + return false; +#endif } -MonoObject* MProperty::GetAttribute(MClass* monoClass) const +MObject* MProperty::GetAttribute(MClass* monoClass) const { +#if USE_MONO MonoClass* parentClass = mono_property_get_parent(_monoProperty); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_property(parentClass, _monoProperty); if (attrInfo == nullptr) @@ -162,14 +175,18 @@ MonoObject* MProperty::GetAttribute(MClass* monoClass) const MonoObject* foundAttr = mono_custom_attrs_get_attr(attrInfo, monoClass->GetNative()); mono_custom_attrs_free(attrInfo); return foundAttr; +#else + return nullptr; +#endif } -const Array& MProperty::GetAttributes() +const Array& MProperty::GetAttributes() { if (_hasCachedAttributes) return _attributes; _hasCachedAttributes = true; +#if USE_MONO MonoClass* parentClass = mono_property_get_parent(_monoProperty); MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_property(parentClass, _monoProperty); if (attrInfo == nullptr) @@ -179,9 +196,8 @@ const Array& MProperty::GetAttributes() const auto length = (uint32)mono_array_length(monoAttributesArray); _attributes.Resize(length); for (uint32 i = 0; i < length; i++) - _attributes[i] = mono_array_get(monoAttributesArray, MonoObject*, i); + _attributes[i] = mono_array_get(monoAttributesArray, MonoObject *, i); mono_custom_attrs_free(attrInfo); +#endif return _attributes; } - -#endif diff --git a/Source/Engine/Scripting/ManagedCLR/MProperty.h b/Source/Engine/Scripting/ManagedCLR/MProperty.h index f1461da1e..0821a6a07 100644 --- a/Source/Engine/Scripting/ManagedCLR/MProperty.h +++ b/Source/Engine/Scripting/ManagedCLR/MProperty.h @@ -25,12 +25,12 @@ protected: MString _name; - Array _attributes; - int32 _hasCachedAttributes : 1; int32 _hasSetMethod : 1; int32 _hasGetMethod : 1; + Array _attributes; + public: #if USE_MONO @@ -47,7 +47,6 @@ public: /// /// Gets the property name. /// - /// The property name. FORCE_INLINE const MString& GetName() const { return _name; @@ -56,7 +55,6 @@ public: /// /// Returns the parent class that this method is contained with. /// - /// The parent class. FORCE_INLINE MClass* GetParentClass() const { return _parentClass; @@ -65,31 +63,26 @@ public: /// /// Gets property type class. /// - /// The property type. MType GetType(); /// /// Gets property get method. /// - /// The getter method. MMethod* GetGetMethod(); /// /// Gets property set method. /// - /// The setter method. MMethod* GetSetMethod(); /// /// Gets property visibility in the class. /// - /// The property visibility. MVisibility GetVisibility(); /// /// Returns true if property is static. /// - /// True if is static, otherwise false. bool IsStatic(); public: @@ -98,23 +91,24 @@ public: /// Retrieves value currently set in the property on the specified object instance. If property is static object instance can be null. /// /// - /// Value will be a pointer to raw data type for value types (for example int, float), and a MonoObject* for reference types. + /// Value will be a pointer to raw data type for value types (for example int, float), and a MObject* for reference types. /// /// The object of given type to get value from. /// An optional pointer to the exception value to store exception object reference. /// The returned boxed value object. - MonoObject* GetValue(MonoObject* instance, MonoObject** exception); + MObject* GetValue(MObject* instance, MObject** exception); /// /// Sets a value for the property on the specified object instance. If property is static object instance can be null. /// /// - /// Value should be a pointer to raw data type for value types (for example int, float), and a MonoObject* for reference types. + /// Value should be a pointer to raw data type for value types (for example int, float), and a MObject* for reference types. /// /// Object of given type to set value to. /// An optional pointer to the exception value to store exception object reference. /// The value to set of undefined type. - void SetValue(MonoObject* instance, void* value, MonoObject** exception); + void SetValue(MObject* instance, void* value, MObject** exception); + public: @@ -136,11 +130,11 @@ public: /// /// The attribute class to take. /// The attribute object. - MonoObject* GetAttribute(MClass* monoClass) const; + MObject* GetAttribute(MClass* monoClass) const; /// /// Returns an instance of all attributes connected with given property. Returns null if the property doesn't have any attributes. /// /// The array of attribute objects. - const Array& GetAttributes(); + const Array& GetAttributes(); }; diff --git a/Source/Engine/Scripting/ManagedCLR/MStaticConverter.h b/Source/Engine/Scripting/ManagedCLR/MStaticConverter.h index 3de031663..ccbb9d269 100644 --- a/Source/Engine/Scripting/ManagedCLR/MStaticConverter.h +++ b/Source/Engine/Scripting/ManagedCLR/MStaticConverter.h @@ -3,7 +3,9 @@ #pragma once #include "Engine/Core/Types/String.h" +#if USE_MONO #include +#endif /// /// Class for converting mono classes and methods into usable form without instancing a class. @@ -13,6 +15,7 @@ class MStaticConverter { public: +#if USE_MONO static MonoClass* GetMonoClassFromObject(MonoObject* monoObject) { ASSERT(monoObject); @@ -63,4 +66,5 @@ public: } return array; } +#endif }; diff --git a/Source/Engine/Scripting/ManagedCLR/MType.cpp b/Source/Engine/Scripting/ManagedCLR/MType.cpp index ddb28da37..f1a78b1e9 100644 --- a/Source/Engine/Scripting/ManagedCLR/MType.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MType.cpp @@ -2,9 +2,7 @@ #include "MType.h" #include "MUtils.h" - #if USE_MONO - #include String MType::ToString() const @@ -42,4 +40,11 @@ bool MType::IsByRef() const return mono_type_is_byref(_monoType) != 0; } +#else + +String MType::ToString() const +{ + return String::Empty; +} + #endif diff --git a/Source/Engine/Scripting/ManagedCLR/MType.h b/Source/Engine/Scripting/ManagedCLR/MType.h index 7ff14f1f5..8681fb504 100644 --- a/Source/Engine/Scripting/ManagedCLR/MType.h +++ b/Source/Engine/Scripting/ManagedCLR/MType.h @@ -5,14 +5,13 @@ #include "MTypes.h" /// -/// Contains information about managed type +/// Contains information about managed type. /// class MType { public: #if USE_MONO - MonoType* _monoType; /// @@ -31,7 +30,6 @@ public: : _monoType(nullptr) { } - #endif /// @@ -46,11 +44,9 @@ public: String ToString() const; #if USE_MONO - /// /// Gets mono type handle /// - /// Mono type MonoType* GetNative() const { return _monoType; @@ -78,6 +74,5 @@ public: { return _monoType != nullptr; } - #endif }; diff --git a/Source/Engine/Scripting/ManagedCLR/MTypes.h b/Source/Engine/Scripting/ManagedCLR/MTypes.h index 4a79758b4..7523bc48e 100644 --- a/Source/Engine/Scripting/ManagedCLR/MTypes.h +++ b/Source/Engine/Scripting/ManagedCLR/MTypes.h @@ -2,63 +2,15 @@ #pragma once +#include "../Types.h" #include "Engine/Core/Types/String.h" #include "Engine/Core/Types/StringView.h" -// Enable/disable mono debugging -#define MONO_DEBUG_ENABLE (!BUILD_RELEASE) -#define USE_MONO (1) -#define USE_NETCORE (0) - -#ifndef USE_MONO_AOT -#define USE_MONO_AOT 0 -#define USE_MONO_AOT_MODE MONO_AOT_MODE_NONE -#endif - -// Enables/disables profiling managed world via Mono -#define USE_MONO_PROFILER (COMPILE_WITH_PROFILER) - -// Enables using single (root) app domain for the user scripts -#define USE_SINGLE_DOMAIN 1 - -#if USE_MONO - /// -/// String container for names and typenames used by the managed runtime backend. +/// String container for names and typenames used by the managed runtime backend (8-bit chars). /// typedef StringAnsi MString; -// Mono types declarations -typedef struct _MonoClass MonoClass; -typedef struct _MonoDomain MonoDomain; -typedef struct _MonoImage MonoImage; -typedef struct _MonoAssembly MonoAssembly; -typedef struct _MonoMethod MonoMethod; -typedef struct _MonoProperty MonoProperty; -typedef struct _MonoObject MonoObject; -typedef struct _MonoEvent MonoEvent; -typedef struct _MonoType MonoType; -typedef struct _MonoString MonoString; -typedef struct _MonoArray MonoArray; -typedef struct _MonoReflectionType MonoReflectionType; -typedef struct _MonoReflectionAssembly MonoReflectionAssembly; -typedef struct _MonoException MonoException; -typedef struct _MonoClassField MonoClassField; -typedef MonoObject MObject; - -#endif - -// Forward declarations -class MCore; -class MAssembly; -class MClass; -class MField; -class MMethod; -class MProperty; -class MEvent; -class MDomain; -class MType; - enum class MVisibility { Private, diff --git a/Source/Engine/Scripting/ManagedCLR/MUtils.cpp b/Source/Engine/Scripting/ManagedCLR/MUtils.cpp index 5f894f17e..fcf15815d 100644 --- a/Source/Engine/Scripting/ManagedCLR/MUtils.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MUtils.cpp @@ -22,6 +22,8 @@ #include "Engine/Utilities/StringConverter.h" #include "Engine/Content/Asset.h" +#if USE_MONO + struct _MonoType { union @@ -846,3 +848,5 @@ void* MUtils::VariantToManagedArgPtr(Variant& value, const MType& type, bool& fa failed = true; return nullptr; } + +#endif diff --git a/Source/Engine/Scripting/ManagedCLR/MUtils.h b/Source/Engine/Scripting/ManagedCLR/MUtils.h index f27936d6f..9bda26826 100644 --- a/Source/Engine/Scripting/ManagedCLR/MUtils.h +++ b/Source/Engine/Scripting/ManagedCLR/MUtils.h @@ -8,6 +8,9 @@ #include "Engine/Core/Types/Variant.h" #include "Engine/Core/Collections/Array.h" #include "Engine/Scripting/ScriptingObject.h" + +#if USE_MONO + #include #include @@ -498,3 +501,5 @@ namespace MUtils extern void* VariantToManagedArgPtr(Variant& value, const MType& type, bool& failed); }; + +#endif diff --git a/Source/Engine/Scripting/ManagedSerialization.cpp b/Source/Engine/Scripting/ManagedSerialization.cpp index cd2f9fff4..6448358d1 100644 --- a/Source/Engine/Scripting/ManagedSerialization.cpp +++ b/Source/Engine/Scripting/ManagedSerialization.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "ManagedSerialization.h" +#if USE_MONO #include "Engine/Core/Log.h" #include "Engine/Serialization/Json.h" #include "Engine/Serialization/JsonWriter.h" @@ -26,7 +27,7 @@ void ManagedSerialization::Serialize(ISerializable::SerializeStream& stream, Mon params[1] = &isManagedOnly; // Call serialization tool - MonoObject* exception = nullptr; + MObject* exception = nullptr; // TODO: use method thunk auto invokeResultStr = (MonoString*)StdTypesContainer::Instance()->Json_Serialize->Invoke(nullptr, params, &exception); if (exception) @@ -64,7 +65,7 @@ void ManagedSerialization::SerializeDiff(ISerializable::SerializeStream& stream, params[2] = &isManagedOnly; // Call serialization tool - MonoObject* exception = nullptr; + MObject* exception = nullptr; // TODO: use method thunk auto invokeResultStr = (MonoString*)StdTypesContainer::Instance()->Json_SerializeDiff->Invoke(nullptr, params, &exception); if (exception) @@ -115,7 +116,7 @@ void ManagedSerialization::Deserialize(const StringAnsiView& data, MonoObject* o args[2] = (void*)&len; // Call serialization tool - MonoObject* exception = nullptr; + MObject* exception = nullptr; // TODO: use method thunk StdTypesContainer::Instance()->Json_Deserialize->Invoke(nullptr, args, &exception); if (exception) @@ -124,3 +125,5 @@ void ManagedSerialization::Deserialize(const StringAnsiView& data, MonoObject* o ex.Log(LogType::Error, TEXT("ManagedSerialization::Deserialize")); } } + +#endif diff --git a/Source/Engine/Scripting/ManagedSerialization.h b/Source/Engine/Scripting/ManagedSerialization.h index dd73361f6..501088412 100644 --- a/Source/Engine/Scripting/ManagedSerialization.h +++ b/Source/Engine/Scripting/ManagedSerialization.h @@ -12,6 +12,7 @@ class FLAXENGINE_API ManagedSerialization { public: +#if USE_MONO /// /// Serializes managed object to JSON. /// @@ -40,4 +41,5 @@ public: /// The input data. /// The object to deserialize. static void Deserialize(const StringAnsiView& data, MonoObject* object); +#endif }; diff --git a/Source/Engine/Scripting/Plugins/PluginManager.cpp b/Source/Engine/Scripting/Plugins/PluginManager.cpp index 257af991b..2e0c83e12 100644 --- a/Source/Engine/Scripting/Plugins/PluginManager.cpp +++ b/Source/Engine/Scripting/Plugins/PluginManager.cpp @@ -44,13 +44,14 @@ PluginManagerService PluginManagerServiceInstance; void PluginManagerImpl::LoadPlugin(MClass* klass, bool isEditor) { +#if !COMPILE_WITHOUT_CSHARP if (Internal_LoadPlugin == nullptr) { Internal_LoadPlugin = PluginManager::GetStaticClass()->GetMethod("Internal_LoadPlugin", 2); ASSERT(Internal_LoadPlugin); } - MonoObject* exception = nullptr; + MObject* exception = nullptr; void* params[2]; params[0] = MUtils::GetType(klass->GetNative()); params[1] = &isEditor; @@ -59,6 +60,7 @@ void PluginManagerImpl::LoadPlugin(MClass* klass, bool isEditor) { DebugLog::LogException(exception); } +#endif } void PluginManagerImpl::OnAssemblyLoaded(MAssembly* assembly) @@ -113,10 +115,11 @@ void PluginManagerImpl::OnAssemblyLoaded(MAssembly* assembly) void PluginManagerImpl::OnAssemblyUnloading(MAssembly* assembly) { +#if !COMPILE_WITHOUT_CSHARP // Cleanup plugins from this assembly const auto disposeMethod = PluginManager::GetStaticClass()->GetMethod("Internal_Dispose", 1); ASSERT(disposeMethod); - MonoObject* exception = nullptr; + MObject* exception = nullptr; void* params[1]; params[0] = assembly->GetNative(); disposeMethod->Invoke(nullptr, params, &exception); @@ -124,6 +127,7 @@ void PluginManagerImpl::OnAssemblyUnloading(MAssembly* assembly) { DebugLog::LogException(exception); } +#endif } void PluginManagerImpl::OnBinaryModuleLoaded(BinaryModule* module) @@ -169,13 +173,15 @@ void PluginManagerService::Dispose() PROFILE_CPU_NAMED("Dispose Plugins"); +#if !COMPILE_WITHOUT_CSHARP // Cleanup all plugins const auto disposeMethod = PluginManager::GetStaticClass()->GetMethod("Internal_Dispose"); ASSERT(disposeMethod); - MonoObject* exception = nullptr; + MObject* exception = nullptr; disposeMethod->Invoke(nullptr, nullptr, &exception); if (exception) { DebugLog::LogException(exception); } +#endif } diff --git a/Source/Engine/Scripting/Scripting.Build.cs b/Source/Engine/Scripting/Scripting.Build.cs index aea06590c..442894540 100644 --- a/Source/Engine/Scripting/Scripting.Build.cs +++ b/Source/Engine/Scripting/Scripting.Build.cs @@ -13,7 +13,11 @@ public class Scripting : EngineModule { base.Setup(options); - options.PublicDependencies.Add("mono"); + if (EngineConfiguration.WithCSharp(options)) + { + options.PublicDependencies.Add("mono"); + } + options.PrivateDependencies.Add("Utilities"); } } diff --git a/Source/Engine/Scripting/Scripting.Internal.cpp b/Source/Engine/Scripting/Scripting.Internal.cpp index 1f26fc8b5..db87072c7 100644 --- a/Source/Engine/Scripting/Scripting.Internal.cpp +++ b/Source/Engine/Scripting/Scripting.Internal.cpp @@ -14,7 +14,11 @@ #endif #include "Engine/Core/Types/Pair.h" #include "Engine/Threading/Threading.h" +#if USE_MONO #include +#endif + +#if USE_MONO namespace ProfilerInternal { @@ -99,9 +103,12 @@ namespace ProfilerInternal } } +#endif + class ScriptingInternal { public: +#if USE_MONO static bool HasGameModulesLoaded() { return Scripting::HasGameModulesLoaded(); @@ -117,9 +124,11 @@ public: ASSERT(IsInMainThread()); ObjectsRemovalService::Flush(); } +#endif static void InitRuntime() { +#if USE_MONO // Scripting API ADD_INTERNAL_CALL("FlaxEngine.Scripting::HasGameModulesLoaded", &HasGameModulesLoaded); ADD_INTERNAL_CALL("FlaxEngine.Scripting::IsTypeFromGameScripts", &IsTypeFromGameScripts); @@ -130,6 +139,7 @@ public: ADD_INTERNAL_CALL("FlaxEngine.Profiler::EndEvent", &ProfilerInternal::EndEvent); ADD_INTERNAL_CALL("FlaxEngine.Profiler::BeginEventGPU", &ProfilerInternal::BeginEventGPU); ADD_INTERNAL_CALL("FlaxEngine.Profiler::EndEventGPU", &ProfilerInternal::EndEventGPU); +#endif } }; diff --git a/Source/Engine/Scripting/Scripting.cpp b/Source/Engine/Scripting/Scripting.cpp index d97718432..78138c01c 100644 --- a/Source/Engine/Scripting/Scripting.cpp +++ b/Source/Engine/Scripting/Scripting.cpp @@ -30,8 +30,10 @@ #include "Engine/Engine/Globals.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Serialization/JsonTools.h" +#if USE_MONO #include #include +#endif extern void registerFlaxEngineInternalCalls(); @@ -55,8 +57,8 @@ public: namespace { - MDomain* _monoRootDomain = nullptr; - MDomain* _monoScriptsDomain = nullptr; + MDomain* _rootDomain = nullptr; + MDomain* _scriptsDomain = nullptr; CriticalSection _objectsLocker; #define USE_OBJECTS_DISPOSE_CRASHES_DEBUGGING 0 #if USE_OBJECTS_DISPOSE_CRASHES_DEBUGGING @@ -134,24 +136,24 @@ bool ScriptingService::Init() engineAssembly->Unloading.Bind(onEngineUnloading); // Initialize managed runtime - if (MCore::Instance()->LoadEngine()) + if (MCore::LoadEngine()) { LOG(Fatal, "Mono initialization failed."); return true; } // Cache root domain - _monoRootDomain = MCore::Instance()->GetRootDomain(); + _rootDomain = MCore::GetRootDomain(); -#if USE_SINGLE_DOMAIN +#if USE_SCRIPTING_SINGLE_DOMAIN // Use single root domain - auto domain = _monoRootDomain; + auto domain = _rootDomain; #else - // Create Mono domain for scripts - auto domain = MCore::Instance()->CreateDomain(TEXT("Scripts Domain")); + // Create Mono domain for scripts + auto domain = MCore::CreateDomain("Scripts Domain"); #endif domain->SetCurrentDomain(true); - _monoScriptsDomain = domain; + _scriptsDomain = domain; // Add internal calls registerFlaxEngineInternalCalls(); @@ -169,6 +171,9 @@ bool ScriptingService::Init() return false; } +#if COMPILE_WITHOUT_CSHARP +#define INVOKE_EVENT(name) +#else #define INVOKE_EVENT(name) \ if (!_isEngineAssemblyLoaded) return; \ if (_method_##name == nullptr) \ @@ -186,9 +191,10 @@ bool ScriptingService::Init() return; \ } \ } \ - MonoObject* exception = nullptr; \ + MObject* exception = nullptr; \ _method_##name->Invoke(nullptr, nullptr, &exception); \ DebugLog::LogException(exception) +#endif void ScriptingService::Update() { @@ -227,12 +233,12 @@ void ScriptingService::BeforeExit() MDomain* Scripting::GetRootDomain() { - return _monoRootDomain; + return _rootDomain; } MDomain* Scripting::GetScriptsDomain() { - return _monoScriptsDomain; + return _scriptsDomain; } void Scripting::ProcessBuildInfoPath(String& path, const String& projectFolderPath) @@ -276,10 +282,9 @@ bool Scripting::LoadBinaryModules(const String& path, const String& projectFolde // Load all references auto referencesMember = document.FindMember("References"); - if (referencesMember != document.MemberEnd()) + if (referencesMember != document.MemberEnd() && referencesMember->value.IsArray()) { auto& referencesArray = referencesMember->value; - ASSERT(referencesArray.IsArray()); for (rapidjson::SizeType i = 0; i < referencesArray.Size(); i++) { auto& reference = referencesArray[i]; @@ -308,10 +313,9 @@ bool Scripting::LoadBinaryModules(const String& path, const String& projectFolde // Load all binary modules auto binaryModulesMember = document.FindMember("BinaryModules"); - if (binaryModulesMember != document.MemberEnd()) + if (binaryModulesMember != document.MemberEnd() && binaryModulesMember->value.IsArray()) { auto& binaryModulesArray = binaryModulesMember->value; - ASSERT(binaryModulesArray.IsArray()); for (rapidjson::SizeType i = 0; i < binaryModulesArray.Size(); i++) { auto& binaryModule = binaryModulesArray[i]; @@ -396,6 +400,7 @@ bool Scripting::LoadBinaryModules(const String& path, const String& projectFolde } } +#if !COMPILE_WITHOUT_CSHARP // C# if (managedPath.HasChars() && !((ManagedBinaryModule*)module)->Assembly->IsLoaded()) { @@ -405,6 +410,7 @@ bool Scripting::LoadBinaryModules(const String& path, const String& projectFolde return true; } } +#endif BinaryModuleLoaded(module); } @@ -419,12 +425,14 @@ bool Scripting::Load() // Note: this action can be called from main thread (due to Mono problems with assemblies actions from other threads) ASSERT(IsInMainThread()); +#if !COMPILE_WITHOUT_CSHARP // Load C# core assembly if (GetBinaryModuleCorlib()->Assembly->Load(mono_get_corlib())) { LOG(Error, "Failed to load corlib C# assembly."); return true; } +#endif // Load FlaxEngine const String flaxEnginePath = Globals::BinariesFolder / TEXT("FlaxEngine.CSharp.dll"); @@ -539,7 +547,7 @@ void Scripting::Release() ObjectsRemovalService::Flush(); // Switch domain - auto rootDomain = MCore::Instance()->GetRootDomain(); + auto rootDomain = MCore::GetRootDomain(); if (rootDomain) { if (!rootDomain->SetCurrentDomain(false)) @@ -548,8 +556,8 @@ void Scripting::Release() } } -#if !USE_SINGLE_DOMAIN - MCore::Instance()->UnloadDomain("Scripts Domain"); +#if !USE_SCRIPTING_SINGLE_DOMAIN + MCore::UnloadDomain("Scripts Domain"); #endif } @@ -647,25 +655,6 @@ void Scripting::Reload(bool canTriggerSceneReload) #endif -MClass* Scripting::FindClass(MonoClass* monoClass) -{ - if (monoClass == nullptr) - return nullptr; - PROFILE_CPU(); - auto& modules = BinaryModule::GetModules(); - for (auto module : modules) - { - auto managedModule = dynamic_cast(module); - if (managedModule && managedModule->Assembly->IsLoaded()) - { - MClass* result = managedModule->Assembly->GetClass(monoClass); - if (result != nullptr) - return result; - } - } - return nullptr; -} - MClass* Scripting::FindClass(const StringAnsiView& fullname) { if (fullname.IsEmpty()) @@ -685,6 +674,27 @@ MClass* Scripting::FindClass(const StringAnsiView& fullname) return nullptr; } +#if USE_MONO + +MClass* Scripting::FindClass(MonoClass* monoClass) +{ + if (monoClass == nullptr) + return nullptr; + PROFILE_CPU(); + auto& modules = BinaryModule::GetModules(); + for (auto module : modules) + { + auto managedModule = dynamic_cast(module); + if (managedModule && managedModule->Assembly->IsLoaded()) + { + MClass* result = managedModule->Assembly->GetClass(monoClass); + if (result != nullptr) + return result; + } + } + return nullptr; +} + MonoClass* Scripting::FindClassNative(const StringAnsiView& fullname) { if (fullname.IsEmpty()) @@ -704,6 +714,8 @@ MonoClass* Scripting::FindClassNative(const StringAnsiView& fullname) return nullptr; } +#endif + ScriptingTypeHandle Scripting::FindScriptingType(const StringAnsiView& fullname) { if (fullname.IsEmpty()) @@ -816,7 +828,7 @@ ScriptingObject* Scripting::TryFindObject(Guid id, MClass* type) return result; } -ScriptingObject* Scripting::FindObject(const MonoObject* managedInstance) +ScriptingObject* Scripting::FindObject(const MObject* managedInstance) { if (managedInstance == nullptr) return nullptr; @@ -938,13 +950,14 @@ bool initFlaxEngine() if (StdTypesContainer::Instance()->Gather()) return true; +#if !COMPILE_WITHOUT_CSHARP // Init C# class library { auto scriptingClass = Scripting::GetStaticClass(); ASSERT(scriptingClass); const auto initMethod = scriptingClass->GetMethod("Init"); ASSERT(initMethod); - MonoObject* exception = nullptr; + MObject* exception = nullptr; initMethod->Invoke(nullptr, nullptr, &exception); if (exception) { @@ -952,10 +965,11 @@ bool initFlaxEngine() ex.Log(LogType::Fatal, TEXT("FlaxEngine.Scripting.Init")); return true; } - - // TODO: move it somewhere to game instance class or similar - MainRenderTask::Instance = New(); } +#endif + + // TODO: move it somewhere to game instance class or similar + MainRenderTask::Instance = New(); return false; } @@ -989,5 +1003,5 @@ void ScriptingService::Dispose() { Scripting::Release(); - MCore::Instance()->UnloadEngine(); + MCore::UnloadEngine(); } diff --git a/Source/Engine/Scripting/Scripting.h b/Source/Engine/Scripting/Scripting.h index 52b532795..341563964 100644 --- a/Source/Engine/Scripting/Scripting.h +++ b/Source/Engine/Scripting/Scripting.h @@ -47,12 +47,12 @@ public: public: /// - /// Gets mono root domain + /// Gets the root domain. /// static MDomain* GetRootDomain(); /// - /// Gets scripts domain + /// Gets the scripts domain (it can be the root domain if not using separate domain for scripting). /// static MDomain* GetScriptsDomain(); @@ -70,17 +70,23 @@ public: static void Release(); #if USE_EDITOR - /// /// Reloads scripts. /// /// True if allow to scene scripts reload callback, otherwise it won't be possible. static void Reload(bool canTriggerSceneReload = true); - #endif public: + /// + /// Finds the class with given fully qualified name within whole assembly. + /// + /// The full name of the type eg: System.Int64. + /// The MClass object or null if missing. + static MClass* FindClass(const StringAnsiView& fullname); + +#if USE_MONO /// /// Finds the class from the given Mono class object within whole assembly. /// @@ -88,19 +94,13 @@ public: /// The MClass object or null if missing. static MClass* FindClass(MonoClass* monoClass); - /// - /// Finds the class with given fully qualified name within whole assembly. - /// - /// The full name of the type eg: System.Int64. - /// The MClass object or null if missing. - static MClass* FindClass(const StringAnsiView& fullname); - /// /// Finds the native class with given fully qualified name within whole assembly. /// /// The full name of the type eg: System.Int64. /// The MClass object or null if missing. static MonoClass* FindClassNative(const StringAnsiView& fullname); +#endif /// /// Finds the scripting type of the given fullname by searching loaded scripting assemblies. @@ -161,7 +161,7 @@ public: /// /// The managed instance pointer. /// The found object or null if missing. - static ScriptingObject* FindObject(const MonoObject* managedInstance); + static ScriptingObject* FindObject(const MObject* managedInstance); /// /// Event called by the internal call on a finalizer thread when the managed objects gets deleted by the GC. diff --git a/Source/Engine/Scripting/ScriptingCalls.h b/Source/Engine/Scripting/ScriptingCalls.h index d76361bee..ee0521b26 100644 --- a/Source/Engine/Scripting/ScriptingCalls.h +++ b/Source/Engine/Scripting/ScriptingCalls.h @@ -4,14 +4,14 @@ #include "Engine/Scripting/ManagedCLR/MTypes.h" -typedef void (*Thunk_Void_0)(MonoObject** exception); -typedef void (*Thunk_Void_1)(void* param_1, MonoObject** exception); -typedef void (*Thunk_Void_2)(void* param_1, void* param_2, MonoObject** exception); -typedef void (*Thunk_Void_3)(void* param_1, void* param_2, void* param_3, MonoObject** exception); -typedef void (*Thunk_Void_4)(void* param_1, void* param_2, void* param_3, void* param_4, MonoObject** exception); +typedef void (*Thunk_Void_0)(MObject** exception); +typedef void (*Thunk_Void_1)(void* param_1, MObject** exception); +typedef void (*Thunk_Void_2)(void* param_1, void* param_2, MObject** exception); +typedef void (*Thunk_Void_3)(void* param_1, void* param_2, void* param_3, MObject** exception); +typedef void (*Thunk_Void_4)(void* param_1, void* param_2, void* param_3, void* param_4, MObject** exception); -typedef MonoObject* (*Thunk_Object_0)(MonoObject** exception); -typedef MonoObject* (*Thunk_Object_1)(void* param_1, MonoObject** exception); -typedef MonoObject* (*Thunk_Object_2)(void* param_1, void* param_2, MonoObject** exception); -typedef MonoObject* (*Thunk_Object_3)(void* param_1, void* param_2, void* param_3, MonoObject** exception); -typedef MonoObject* (*Thunk_Object_4)(void* param_1, void* param_2, void* param_3, void* param_4, MonoObject** exception); +typedef MObject* (*Thunk_Object_0)(MObject** exception); +typedef MObject* (*Thunk_Object_1)(void* param_1, MObject** exception); +typedef MObject* (*Thunk_Object_2)(void* param_1, void* param_2, MObject** exception); +typedef MObject* (*Thunk_Object_3)(void* param_1, void* param_2, void* param_3, MObject** exception); +typedef MObject* (*Thunk_Object_4)(void* param_1, void* param_2, void* param_3, void* param_4, MObject** exception); diff --git a/Source/Engine/Scripting/ScriptingObject.cpp b/Source/Engine/Scripting/ScriptingObject.cpp index 52ebbd443..8090c529f 100644 --- a/Source/Engine/Scripting/ScriptingObject.cpp +++ b/Source/Engine/Scripting/ScriptingObject.cpp @@ -18,8 +18,10 @@ #include "ManagedCLR/MCore.h" #endif #include "FlaxEngine.Gen.h" +#if USE_MONO #include #include +#endif #define ScriptingObject_unmanagedPtr "__unmanagedPtr" #define ScriptingObject_id "__internalId" @@ -54,14 +56,18 @@ ScriptingObject::~ScriptingObject() } } -MonoObject* ScriptingObject::GetManagedInstance() const +MObject* ScriptingObject::GetManagedInstance() const { +#if USE_MONO return _gcHandle ? mono_gchandle_get_target(_gcHandle) : nullptr; +#else + return nullptr; +#endif } -MonoObject* ScriptingObject::GetOrCreateManagedInstance() const +MObject* ScriptingObject::GetOrCreateManagedInstance() const { - MonoObject* managedInstance = GetManagedInstance(); + MObject* managedInstance = GetManagedInstance(); if (!managedInstance) { const_cast(this)->CreateManaged(); @@ -144,9 +150,10 @@ void* ScriptingObject::ToInterface(ScriptingObject* obj, const ScriptingTypeHand return result; } -ScriptingObject* ScriptingObject::ToNative(MonoObject* obj) +ScriptingObject* ScriptingObject::ToNative(MObject* obj) { ScriptingObject* ptr = nullptr; +#if USE_MONO if (obj) { // TODO: cache the field offset from object and read directly from object pointer @@ -154,6 +161,7 @@ ScriptingObject* ScriptingObject::ToNative(MonoObject* obj) CHECK_RETURN(ptrField, nullptr); mono_field_get_value(obj, ptrField, &ptr); } +#endif return ptr; } @@ -191,7 +199,9 @@ void ScriptingObject::OnManagedInstanceDeleted() // Release the handle if (_gcHandle) { +#if USE_MONO mono_gchandle_free(_gcHandle); +#endif _gcHandle = 0; } @@ -212,6 +222,8 @@ void ScriptingObject::OnScriptingDispose() DeleteObject(); } +#if USE_MONO + MonoObject* ScriptingObject::CreateManagedInternal() { #if BUILD_DEBUG @@ -254,8 +266,11 @@ MonoObject* ScriptingObject::CreateManagedInternal() return managedInstance; } +#endif + void ScriptingObject::DestroyManaged() { +#if USE_MONO // Get managed instance const auto managedInstance = GetManagedInstance(); @@ -279,6 +294,9 @@ void ScriptingObject::DestroyManaged() mono_gchandle_free(_gcHandle); _gcHandle = 0; } +#else + _gcHandle = 0; +#endif } void ScriptingObject::RegisterObject() @@ -319,6 +337,8 @@ bool ScriptingObject::CanCast(MClass* from, MClass* to) return from->IsSubClassOf(to); } +#if USE_MONO + bool ScriptingObject::CanCast(MClass* from, MonoClass* to) { if (!from && !to) @@ -333,6 +353,8 @@ bool ScriptingObject::CanCast(MClass* from, MonoClass* to) return from->IsSubClassOf(to); } +#endif + void ScriptingObject::OnDeleteObject() { // Cleanup managed object @@ -358,6 +380,7 @@ ManagedScriptingObject::ManagedScriptingObject(const SpawnParams& params) void ManagedScriptingObject::CreateManaged() { +#if USE_MONO MonoObject* managedInstance = CreateManagedInternal(); if (managedInstance) { @@ -368,6 +391,11 @@ void ManagedScriptingObject::CreateManaged() if (!IsRegistered()) RegisterObject(); } +#else + // Ensure to be registered + if (!IsRegistered()) + RegisterObject(); +#endif } PersistentScriptingObject::PersistentScriptingObject(const SpawnParams& params) @@ -385,7 +413,9 @@ void PersistentScriptingObject::OnManagedInstanceDeleted() // Cleanup if (_gcHandle) { +#if USE_MONO mono_gchandle_free(_gcHandle); +#endif _gcHandle = 0; } @@ -404,6 +434,7 @@ void PersistentScriptingObject::OnScriptingDispose() void PersistentScriptingObject::CreateManaged() { +#if USE_MONO MonoObject* managedInstance = CreateManagedInternal(); if (managedInstance) { @@ -414,11 +445,18 @@ void PersistentScriptingObject::CreateManaged() if (!IsRegistered()) RegisterObject(); } +#else + // Ensure to be registered + if (!IsRegistered()) + RegisterObject(); +#endif } class ScriptingObjectInternal { public: + +#if !COMPILE_WITHOUT_CSHARP static MonoObject* Create1(MonoReflectionType* type) { @@ -676,6 +714,14 @@ public: ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_GetUnmanagedInterface", &GetUnmanagedInterface); } +#else + + static void InitRuntime() + { + } + +#endif + static ScriptingObject* Spawn(const ScriptingObjectSpawnParams& params) { return New(params); diff --git a/Source/Engine/Scripting/ScriptingObject.h b/Source/Engine/Scripting/ScriptingObject.h index 01d4eb33c..9846b05fe 100644 --- a/Source/Engine/Scripting/ScriptingObject.h +++ b/Source/Engine/Scripting/ScriptingObject.h @@ -62,12 +62,12 @@ public: /// /// Gets the managed instance object. /// - MonoObject* GetManagedInstance() const; + MObject* GetManagedInstance() const; /// /// Gets the managed instance object or creates it if missing. /// - MonoObject* GetOrCreateManagedInstance() const; + MObject* GetOrCreateManagedInstance() const; /// /// Determines whether managed instance is alive. @@ -117,9 +117,9 @@ public: return (T*)ToInterface(obj, T::TypeInitializer); } - static ScriptingObject* ToNative(MonoObject* obj); + static ScriptingObject* ToNative(MObject* obj); - static MonoObject* ToManaged(ScriptingObject* obj) + static MObject* ToManaged(ScriptingObject* obj) { return obj ? obj->GetOrCreateManagedInstance() : nullptr; } @@ -139,7 +139,9 @@ public: /// The destination class to the cast. /// True if can, otherwise false. static bool CanCast(MClass* from, MClass* to); +#if USE_MONO static bool CanCast(MClass* from, MonoClass* to); +#endif template static T* Cast(ScriptingObject* obj) @@ -154,10 +156,12 @@ public: return CanCast(GetClass(), type); } +#if USE_MONO bool Is(MonoClass* klass) const { return CanCast(GetClass(), klass); } +#endif template bool Is() const @@ -186,7 +190,6 @@ public: /// /// Determines whether this object is registered or not (can be found by the queries and used in a game). /// - /// true if this instance is registered; otherwise, false. FORCE_INLINE bool IsRegistered() const { return (Flags & ObjectFlags::IsRegistered) != 0; @@ -204,10 +207,12 @@ public: protected: +#if USE_MONO /// /// Create a new managed object. /// MonoObject* CreateManagedInternal(); +#endif public: diff --git a/Source/Engine/Scripting/ScriptingObjectReference.h b/Source/Engine/Scripting/ScriptingObjectReference.h index 937e92ce1..3de0498e7 100644 --- a/Source/Engine/Scripting/ScriptingObjectReference.h +++ b/Source/Engine/Scripting/ScriptingObjectReference.h @@ -68,7 +68,7 @@ public: /// /// Gets managed instance object (or null if no object linked). /// - FORCE_INLINE MonoObject* GetManagedInstance() const + FORCE_INLINE MObject* GetManagedInstance() const { return _object ? _object->GetOrCreateManagedInstance() : nullptr; } @@ -84,7 +84,7 @@ public: /// /// Gets the managed instance object or creates it if missing or null if not assigned. /// - FORCE_INLINE MonoObject* GetOrCreateManagedInstance() const + FORCE_INLINE MObject* GetOrCreateManagedInstance() const { return _object ? _object->GetOrCreateManagedInstance() : nullptr; } diff --git a/Source/Engine/Scripting/ScriptingType.h b/Source/Engine/Scripting/ScriptingType.h index 1e18c3e7d..3a20377e4 100644 --- a/Source/Engine/Scripting/ScriptingType.h +++ b/Source/Engine/Scripting/ScriptingType.h @@ -13,9 +13,6 @@ class NativeBinaryModule; struct ScriptingTypeHandle; struct ScriptingTypeInitializer; struct ScriptingObjectSpawnParams; -typedef struct _MonoClass MonoClass; -typedef struct _MonoObject MonoObject; -typedef struct _MonoType MonoType; /// /// The safe handle to the scripting type contained in the scripting assembly. @@ -113,8 +110,8 @@ struct FLAXENGINE_API ScriptingType typedef void (*Ctor)(void* ptr); typedef void (*Dtor)(void* ptr); typedef void (*Copy)(void* dst, void* src); - typedef MonoObject* (*Box)(void* ptr); - typedef void (*Unbox)(void* ptr, MonoObject* managed); + typedef MObject* (*Box)(void* ptr); + typedef void (*Unbox)(void* ptr, MObject* managed); typedef void (*GetField)(void* ptr, const String& name, Variant& value); typedef void (*SetField)(void* ptr, const String& name, const Variant& value); typedef void* (*GetInterfaceWrapper)(ScriptingObject* obj); diff --git a/Source/Engine/Scripting/SoftObjectReference.h b/Source/Engine/Scripting/SoftObjectReference.h index e03ee81d0..e5c8cac28 100644 --- a/Source/Engine/Scripting/SoftObjectReference.h +++ b/Source/Engine/Scripting/SoftObjectReference.h @@ -281,7 +281,7 @@ public: /// Gets managed instance object (or null if no object linked). /// /// The managed object instance. - MonoObject* GetManagedInstance() const + MObject* GetManagedInstance() const { auto object = Get(); return object ? object->GetOrCreateManagedInstance() : nullptr; @@ -301,7 +301,7 @@ public: /// Gets the managed instance object or creates it if missing or null if not assigned. /// /// The Mono managed object. - MonoObject* GetOrCreateManagedInstance() const + MObject* GetOrCreateManagedInstance() const { auto object = Get(); return object ? object->GetOrCreateManagedInstance() : nullptr; diff --git a/Source/Engine/Scripting/StdTypesContainer.cpp b/Source/Engine/Scripting/StdTypesContainer.cpp index b68916e50..83c164f1a 100644 --- a/Source/Engine/Scripting/StdTypesContainer.cpp +++ b/Source/Engine/Scripting/StdTypesContainer.cpp @@ -47,6 +47,7 @@ void StdTypesContainer::Clear() bool StdTypesContainer::Gather() { +#if !COMPILE_WITHOUT_CSHARP #define GET_CLASS(assembly, type, typeName) \ type = ((ManagedBinaryModule*)CONCAT_MACROS(GetBinaryModule, assembly)())->Assembly->GetClass(typeName); \ if (type == nullptr) \ @@ -93,5 +94,6 @@ bool StdTypesContainer::Gather() #undef GET_CLASS #undef GET_METHOD +#endif return false; } diff --git a/Source/Engine/Scripting/Types.h b/Source/Engine/Scripting/Types.h index 8f52524ec..d9ea2bf77 100644 --- a/Source/Engine/Scripting/Types.h +++ b/Source/Engine/Scripting/Types.h @@ -2,14 +2,69 @@ #pragma once +// Forward declarations class Scripting; struct ScriptingType; class BinaryModule; class ScriptingObject; +class MCore; class MDomain; class MException; class MAssembly; class MClass; class MField; +class MMethod; class MProperty; class MEvent; +class MDomain; +class MType; + +#if COMPILE_WITHOUT_CSHARP + +// No Scripting +#define USE_MONO 0 +#define USE_NETCORE 0 +typedef void MObject; + +#else + +#define USE_MONO 1 +#define USE_NETCORE 0 + +// Enables using single (root) app domain for the user scripts +#define USE_SCRIPTING_SINGLE_DOMAIN 1 + +#if USE_MONO + +// Enables/disables profiling managed world via Mono +#define USE_MONO_PROFILER (COMPILE_WITH_PROFILER) + +// Enable/disable mono debugging +#define MONO_DEBUG_ENABLE (!BUILD_RELEASE) + +#ifndef USE_MONO_AOT +#define USE_MONO_AOT 0 +#define USE_MONO_AOT_MODE MONO_AOT_MODE_NONE +#endif + +// Mono types declarations +typedef struct _MonoClass MonoClass; +typedef struct _MonoDomain MonoDomain; +typedef struct _MonoImage MonoImage; +typedef struct _MonoAssembly MonoAssembly; +typedef struct _MonoMethod MonoMethod; +typedef struct _MonoProperty MonoProperty; +typedef struct _MonoObject MonoObject; +typedef struct _MonoEvent MonoEvent; +typedef struct _MonoType MonoType; +typedef struct _MonoString MonoString; +typedef struct _MonoArray MonoArray; +typedef struct _MonoReflectionType MonoReflectionType; +typedef struct _MonoReflectionAssembly MonoReflectionAssembly; +typedef struct _MonoException MonoException; +typedef struct _MonoClassField MonoClassField; +typedef MonoObject MObject; + +#endif + +#endif diff --git a/Source/Engine/Serialization/Serialization.cpp b/Source/Engine/Serialization/Serialization.cpp index 7b347f160..ec2785997 100644 --- a/Source/Engine/Serialization/Serialization.cpp +++ b/Source/Engine/Serialization/Serialization.cpp @@ -208,12 +208,14 @@ void Serialization::Serialize(ISerializable::SerializeStream& stream, const Vari case VariantType::ManagedObject: case VariantType::Structure: { +#if USE_MONO MonoObject* obj; if (v.Type.Type == VariantType::Structure) obj = MUtils::BoxVariant(v); else obj = (MonoObject*)v; ManagedSerialization::Serialize(stream, obj); +#endif break; } default: @@ -346,6 +348,7 @@ void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Varian case VariantType::ManagedObject: case VariantType::Structure: { +#if USE_MONO auto obj = (MonoObject*)v; if (!obj && v.Type.TypeName) { @@ -369,6 +372,7 @@ void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Varian ManagedSerialization::Deserialize(value, obj); if (v.Type.Type == VariantType::Structure) v = MUtils::UnboxVariant(obj); +#endif break; } default: diff --git a/Source/Engine/Serialization/Stream.cpp b/Source/Engine/Serialization/Stream.cpp index 298799a05..dafaf3e22 100644 --- a/Source/Engine/Serialization/Stream.cpp +++ b/Source/Engine/Serialization/Stream.cpp @@ -356,6 +356,7 @@ void ReadStream::ReadVariant(Variant* data) // Json StringAnsi json; ReadStringAnsi(&json, -71); +#if USE_MONO MCore::AttachThread(); MonoClass* klass = MUtils::GetClass(data->Type); if (!klass) @@ -376,6 +377,7 @@ void ReadStream::ReadVariant(Variant* data) data->SetManagedObject(obj); else *data = MUtils::UnboxVariant(obj); +#endif } else { @@ -706,6 +708,7 @@ void WriteStream::WriteVariant(const Variant& data) case VariantType::ManagedObject: case VariantType::Structure: { +#if USE_MONO MonoObject* obj; if (data.Type.Type == VariantType::Structure) obj = MUtils::BoxVariant(data); @@ -721,6 +724,7 @@ void WriteStream::WriteVariant(const Variant& data) WriteStringAnsi(StringAnsiView(json.GetString(), (int32)json.GetSize()), -71); } else +#endif { WriteByte(0); } diff --git a/Source/Engine/Threading/JobSystem.cpp b/Source/Engine/Threading/JobSystem.cpp index 56d23901c..4898014f9 100644 --- a/Source/Engine/Threading/JobSystem.cpp +++ b/Source/Engine/Threading/JobSystem.cpp @@ -183,7 +183,7 @@ int32 JobSystemThread::Run() // Ensure to have C# thread attached to this thead (late init due to MCore being initialized after Job System) if (attachMonoThread && !mono_domain_get()) { - const auto domain = MCore::Instance()->GetActiveDomain(); + const auto domain = MCore::GetActiveDomain(); mono_thread_attach(domain->GetNative()); attachMonoThread = false; } diff --git a/Source/Engine/UI/UICanvas.cpp b/Source/Engine/UI/UICanvas.cpp index 3d6310ee4..0b5f32b4e 100644 --- a/Source/Engine/UI/UICanvas.cpp +++ b/Source/Engine/UI/UICanvas.cpp @@ -5,8 +5,13 @@ #include "Engine/Scripting/ManagedCLR/MMethod.h" #include "Engine/Scripting/ManagedCLR/MClass.h" #include "Engine/Serialization/Serialization.h" +#if USE_MONO #include +#endif +#if COMPILE_WITHOUT_CSHARP +#define UICANVAS_INVOKE(event) +#else // Cached methods (FlaxEngine.CSharp.dll is loaded only once) MMethod* UICanvas_Serialize = nullptr; MMethod* UICanvas_SerializeDiff = nullptr; @@ -24,7 +29,7 @@ MMethod* UICanvas_ParentChanged = nullptr; auto instance = GetManagedInstance(); \ if (instance) \ { \ - MonoObject* exception = nullptr; \ + MObject* exception = nullptr; \ UICanvas_##event->Invoke(instance, nullptr, &exception); \ if (exception) \ { \ @@ -32,10 +37,12 @@ MMethod* UICanvas_ParentChanged = nullptr; ex.Log(LogType::Error, TEXT("UICanvas::" #event)); \ } \ } +#endif UICanvas::UICanvas(const SpawnParams& params) : Actor(params) { +#if !COMPILE_WITHOUT_CSHARP Platform::MemoryBarrier(); if (UICanvas_Serialize == nullptr) { @@ -52,6 +59,7 @@ UICanvas::UICanvas(const SpawnParams& params) UICanvas_EndPlay = mclass->GetMethod("EndPlay"); UICanvas_ParentChanged = mclass->GetMethod("ParentChanged"); } +#endif } #if USE_EDITOR @@ -71,10 +79,11 @@ void UICanvas::Serialize(SerializeStream& stream, const void* otherObj) SERIALIZE_GET_OTHER_OBJ(UICanvas); +#if !COMPILE_WITHOUT_CSHARP stream.JKEY("V"); void* params[1]; params[0] = other ? other->GetOrCreateManagedInstance() : nullptr; - MonoObject* exception = nullptr; + MObject* exception = nullptr; auto method = other ? UICanvas_SerializeDiff : UICanvas_Serialize; auto invokeResultStr = (MonoString*)method->Invoke(GetOrCreateManagedInstance(), params, &exception); if (exception) @@ -93,6 +102,7 @@ void UICanvas::Serialize(SerializeStream& stream, const void* otherObj) stream.RawValue(invokeResultChars); mono_free(invokeResultChars); } +#endif } void UICanvas::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) @@ -100,6 +110,7 @@ void UICanvas::Deserialize(DeserializeStream& stream, ISerializeModifier* modifi // Base Actor::Deserialize(stream, modifier); +#if !COMPILE_WITHOUT_CSHARP // Handle C# object data serialization const auto dataMember = stream.FindMember("V"); if (dataMember != stream.MemberEnd()) @@ -110,7 +121,7 @@ void UICanvas::Deserialize(DeserializeStream& stream, ISerializeModifier* modifi const auto str = buffer.GetString(); void* args[1]; args[0] = mono_string_new(mono_domain_get(), str); - MonoObject* exception = nullptr; + MObject* exception = nullptr; UICanvas_Deserialize->Invoke(GetOrCreateManagedInstance(), args, &exception); if (exception) { @@ -118,6 +129,7 @@ void UICanvas::Deserialize(DeserializeStream& stream, ISerializeModifier* modifi ex.Log(LogType::Error, TEXT("UICanvas::Deserialize")); } } +#endif if (IsDuringPlay()) { diff --git a/Source/Engine/UI/UIControl.cpp b/Source/Engine/UI/UIControl.cpp index 6afdd77b3..36e4f732e 100644 --- a/Source/Engine/UI/UIControl.cpp +++ b/Source/Engine/UI/UIControl.cpp @@ -6,8 +6,13 @@ #include "Engine/Scripting/ManagedCLR/MClass.h" #include "Engine/Scripting/Scripting.h" #include "Engine/Serialization/Serialization.h" +#if USE_MONO #include +#endif +#if COMPILE_WITHOUT_CSHARP +#define UICONTROL_INVOKE(event) +#else // Cached methods (FlaxEngine.CSharp.dll is loaded only once) MMethod* UIControl_Serialize = nullptr; MMethod* UIControl_SerializeDiff = nullptr; @@ -22,7 +27,7 @@ MMethod* UIControl_EndPlay = nullptr; #define UICONTROL_INVOKE(event) \ if (HasManagedInstance()) \ { \ - MonoObject* exception = nullptr; \ + MObject* exception = nullptr; \ UIControl_##event->Invoke(GetManagedInstance(), nullptr, &exception); \ if (exception) \ { \ @@ -30,10 +35,12 @@ MMethod* UIControl_EndPlay = nullptr; ex.Log(LogType::Error, TEXT("UICanvas::" #event)); \ } \ } +#endif UIControl::UIControl(const SpawnParams& params) : Actor(params) { +#if !COMPILE_WITHOUT_CSHARP if (UIControl_Serialize == nullptr) { MClass* mclass = GetClass(); @@ -47,6 +54,7 @@ UIControl::UIControl(const SpawnParams& params) UIControl_BeginPlay = mclass->GetMethod("BeginPlay"); UIControl_EndPlay = mclass->GetMethod("EndPlay"); } +#endif } #if USE_EDITOR @@ -66,11 +74,12 @@ void UIControl::Serialize(SerializeStream& stream, const void* otherObj) SERIALIZE_GET_OTHER_OBJ(UIControl); +#if !COMPILE_WITHOUT_CSHARP void* params[2]; MonoString* controlType = nullptr; params[0] = &controlType; params[1] = other ? other->GetOrCreateManagedInstance() : nullptr; - MonoObject* exception = nullptr; + MObject* exception = nullptr; const auto method = other ? UIControl_SerializeDiff : UIControl_Serialize; const auto invokeResultStr = (MonoString*)method->Invoke(GetOrCreateManagedInstance(), params, &exception); if (exception) @@ -107,6 +116,7 @@ void UIControl::Serialize(SerializeStream& stream, const void* otherObj) const auto invokeResultChars = mono_string_to_utf8(invokeResultStr); stream.RawValue(invokeResultChars); mono_free(invokeResultChars); +#endif } void UIControl::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) @@ -114,6 +124,7 @@ void UIControl::Deserialize(DeserializeStream& stream, ISerializeModifier* modif // Base Actor::Deserialize(stream, modifier); +#if !COMPILE_WITHOUT_CSHARP MonoReflectionType* typeObj = nullptr; const auto controlMember = stream.FindMember("Control"); if (controlMember != stream.MemberEnd()) @@ -140,7 +151,7 @@ void UIControl::Deserialize(DeserializeStream& stream, ISerializeModifier* modif void* args[2]; args[0] = mono_string_new(mono_domain_get(), str); args[1] = typeObj; - MonoObject* exception = nullptr; + MObject* exception = nullptr; UIControl_Deserialize->Invoke(GetOrCreateManagedInstance(), args, &exception); if (exception) { @@ -148,6 +159,7 @@ void UIControl::Deserialize(DeserializeStream& stream, ISerializeModifier* modif ex.Log(LogType::Error, TEXT("UIControl::Deserialize")); } } +#endif } void UIControl::OnParentChanged() diff --git a/Source/Engine/Visject/VisjectGraph.cpp b/Source/Engine/Visject/VisjectGraph.cpp index d8c2abf3b..1c0c79176 100644 --- a/Source/Engine/Visject/VisjectGraph.cpp +++ b/Source/Engine/Visject/VisjectGraph.cpp @@ -523,6 +523,7 @@ void VisjectExecutor::ProcessGroupPacking(Box* box, Node* node, Value& value) const ScriptingTypeHandle typeHandle = Scripting::FindScriptingType(typeNameAnsiView); if (!typeHandle) { +#if !COMPILE_WITHOUT_CSHARP const auto mclass = Scripting::FindClass(typeNameAnsiView); if (mclass) { @@ -559,6 +560,7 @@ void VisjectExecutor::ProcessGroupPacking(Box* box, Node* node, Value& value) } } else if (typeName.HasChars()) +#endif { OnError(node, box, String::Format(TEXT("Missing type '{0}'"), typeName)); } @@ -609,6 +611,7 @@ void VisjectExecutor::ProcessGroupPacking(Box* box, Node* node, Value& value) const ScriptingTypeHandle typeHandle = Scripting::FindScriptingType(typeNameAnsiView); if (!typeHandle) { +#if !COMPILE_WITHOUT_CSHARP const auto mclass = Scripting::FindClass(typeNameAnsiView); if (mclass) { @@ -646,6 +649,7 @@ void VisjectExecutor::ProcessGroupPacking(Box* box, Node* node, Value& value) } } else if (typeName.HasChars()) +#endif { OnError(node, box, String::Format(TEXT("Missing type '{0}'"), typeName)); } diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs index 0e1e2a818..60194ab36 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs @@ -27,9 +27,19 @@ namespace Flax.Build.Bindings private static readonly HashSet CppVariantFromTypes = new HashSet(); private static bool CppNonPodTypesConvertingGeneration = false; - public static readonly List CppScriptObjectVirtualWrapperMethodsPostfixes = new List + public class ScriptingLangInfo { - "_ManagedWrapper", // C# + public bool Enabled; + public string VirtualWrapperMethodsPostfix; + } + + public static readonly List ScriptingLangInfos = new List + { + new ScriptingLangInfo + { + Enabled = true, + VirtualWrapperMethodsPostfix = "_ManagedWrapper", // C# + }, }; public static event Action, StringBuilder> GenerateCppBinaryModuleHeader; @@ -1003,6 +1013,8 @@ namespace Flax.Build.Bindings private static void GenerateCppManagedWrapperFunction(BuildData buildData, StringBuilder contents, VirtualClassInfo classInfo, FunctionInfo functionInfo, int scriptVTableSize, int scriptVTableIndex) { + if (!EngineConfiguration.WithCSharp(buildData.TargetOptions)) + return; contents.AppendFormat(" {0} {1}_ManagedWrapper(", functionInfo.ReturnType, functionInfo.UniqueName); var separator = false; for (var i = 0; i < functionInfo.Parameters.Count; i++) @@ -1240,13 +1252,17 @@ namespace Flax.Build.Bindings contents.AppendLine(" if (vtableIndex > 0 && vtableIndex < entriesCount)"); contents.AppendLine(" {"); contents.AppendLine($" scriptVTableBase[{scriptVTableIndex} + 2] = vtable[vtableIndex];"); - for (var i = 0; i < CppScriptObjectVirtualWrapperMethodsPostfixes.Count; i++) + for (int i = 0, count = 0; i < ScriptingLangInfos.Count; i++) { - contents.AppendLine(i == 0 ? " if (wrapperIndex == 0)" : $" else if (wrapperIndex == {i})"); + var langInfo = ScriptingLangInfos[i]; + if (!langInfo.Enabled) + continue; + contents.AppendLine(count == 0 ? " if (wrapperIndex == 0)" : $" else if (wrapperIndex == {count})"); contents.AppendLine(" {"); - contents.AppendLine($" auto thunkPtr = &{classInfo.NativeName}Internal::{functionInfo.UniqueName}{CppScriptObjectVirtualWrapperMethodsPostfixes[i]};"); + contents.AppendLine($" auto thunkPtr = &{classInfo.NativeName}Internal::{functionInfo.UniqueName}{langInfo.VirtualWrapperMethodsPostfix};"); contents.AppendLine(" vtable[vtableIndex] = *(void**)&thunkPtr;"); contents.AppendLine(" }"); + count++; } contents.AppendLine(" }"); contents.AppendLine(" else"); @@ -1412,6 +1428,7 @@ namespace Flax.Build.Bindings if (classInfo.Parent != null && !(classInfo.Parent is FileInfo)) classTypeNameInternal = classInfo.Parent.FullNameNative + '_' + classTypeNameInternal; var useScripting = classInfo.IsStatic || classInfo.IsScriptingObject; + var useCSharp = EngineConfiguration.WithCSharp(buildData.TargetOptions); var hasInterface = classInfo.Interfaces != null && classInfo.Interfaces.Any(x => x.Access == AccessLevel.Public); if (classInfo.IsAutoSerialization) @@ -1428,74 +1445,77 @@ namespace Flax.Build.Bindings if (!useScripting) continue; var paramsCount = eventInfo.Type.GenericArgs?.Count ?? 0; - - // C# event invoking wrapper (calls C# event from C++ delegate) - CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h"); - CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MEvent.h"); - CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h"); CppIncludeFiles.Add("Engine/Profiler/ProfilerCPU.h"); - contents.Append(" "); - if (eventInfo.IsStatic) - contents.Append("static "); - contents.AppendFormat("void {0}_ManagedWrapper(", eventInfo.Name); - for (var i = 0; i < paramsCount; i++) - { - if (i != 0) - contents.Append(", "); - contents.Append(eventInfo.Type.GenericArgs[i]).Append(" arg" + i); - } - contents.Append(')').AppendLine(); - contents.Append(" {").AppendLine(); - contents.Append(" static MMethod* mmethod = nullptr;").AppendLine(); - contents.Append(" if (!mmethod)").AppendLine(); - contents.AppendFormat(" mmethod = {1}::TypeInitializer.GetType().ManagedClass->GetMethod(\"Internal_{0}_Invoke\", {2});", eventInfo.Name, classTypeNameNative, paramsCount).AppendLine(); - contents.Append(" CHECK(mmethod);").AppendLine(); - contents.Append($" PROFILE_CPU_NAMED(\"{classInfo.FullNameManaged}::On{eventInfo.Name}\");").AppendLine(); - contents.Append(" MonoObject* exception = nullptr;").AppendLine(); - if (paramsCount == 0) - contents.AppendLine(" void** params = nullptr;"); - else - contents.AppendLine($" void* params[{paramsCount}];"); - for (var i = 0; i < paramsCount; i++) - { - var paramType = eventInfo.Type.GenericArgs[i]; - var paramName = "arg" + i; - var paramValue = GenerateCppWrapperNativeToManagedParam(buildData, contents, paramType, paramName, classInfo, false); - contents.Append($" params[{i}] = {paramValue};").AppendLine(); - } - if (eventInfo.IsStatic) - contents.AppendLine(" MonoObject* instance = nullptr;"); - else - contents.AppendLine($" MonoObject* instance = (({classTypeNameNative}*)this)->GetManagedInstance();"); - contents.Append(" mono_runtime_invoke(mmethod->GetNative(), instance, params, &exception);").AppendLine(); - contents.Append(" if (exception)").AppendLine(); - contents.Append(" DebugLog::LogException(exception);").AppendLine(); - contents.Append(" }").AppendLine().AppendLine(); - - // C# event wrapper binding method (binds/unbinds C# wrapper to C++ delegate) - contents.AppendFormat(" static void {0}_ManagedBind(", eventInfo.Name); - if (!eventInfo.IsStatic) - contents.AppendFormat("{0}* obj, ", classTypeNameNative); - contents.Append("bool bind)").AppendLine(); - contents.Append(" {").AppendLine(); - contents.Append(" Function f;").AppendLine(); - if (eventInfo.IsStatic) - contents.AppendFormat(" f.Bind<{0}_ManagedWrapper>();", eventInfo.Name).AppendLine(); - else - contents.AppendFormat(" f.Bind<{1}Internal, &{1}Internal::{0}_ManagedWrapper>(({1}Internal*)obj);", eventInfo.Name, classTypeNameInternal).AppendLine(); - contents.Append(" if (bind)").AppendLine(); var bindPrefix = eventInfo.IsStatic ? classTypeNameNative + "::" : "obj->"; - contents.AppendFormat(" {0}{1}.Bind(f);", bindPrefix, eventInfo.Name).AppendLine(); - contents.Append(" else").AppendLine(); - contents.AppendFormat(" {0}{1}.Unbind(f);", bindPrefix, eventInfo.Name).AppendLine(); - contents.Append(" }").AppendLine().AppendLine(); + + if (useCSharp) + { + // C# event invoking wrapper (calls C# event from C++ delegate) + CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h"); + CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MEvent.h"); + CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h"); + contents.Append(" "); + if (eventInfo.IsStatic) + contents.Append("static "); + contents.AppendFormat("void {0}_ManagedWrapper(", eventInfo.Name); + for (var i = 0; i < paramsCount; i++) + { + if (i != 0) + contents.Append(", "); + contents.Append(eventInfo.Type.GenericArgs[i]).Append(" arg" + i); + } + contents.Append(')').AppendLine(); + contents.Append(" {").AppendLine(); + contents.Append(" static MMethod* mmethod = nullptr;").AppendLine(); + contents.Append(" if (!mmethod)").AppendLine(); + contents.AppendFormat(" mmethod = {1}::TypeInitializer.GetType().ManagedClass->GetMethod(\"Internal_{0}_Invoke\", {2});", eventInfo.Name, classTypeNameNative, paramsCount).AppendLine(); + contents.Append(" CHECK(mmethod);").AppendLine(); + contents.Append($" PROFILE_CPU_NAMED(\"{classInfo.FullNameManaged}::On{eventInfo.Name}\");").AppendLine(); + contents.Append(" MonoObject* exception = nullptr;").AppendLine(); + if (paramsCount == 0) + contents.AppendLine(" void** params = nullptr;"); + else + contents.AppendLine($" void* params[{paramsCount}];"); + for (var i = 0; i < paramsCount; i++) + { + var paramType = eventInfo.Type.GenericArgs[i]; + var paramName = "arg" + i; + var paramValue = GenerateCppWrapperNativeToManagedParam(buildData, contents, paramType, paramName, classInfo, false); + contents.Append($" params[{i}] = {paramValue};").AppendLine(); + } + if (eventInfo.IsStatic) + contents.AppendLine(" MonoObject* instance = nullptr;"); + else + contents.AppendLine($" MonoObject* instance = (({classTypeNameNative}*)this)->GetManagedInstance();"); + contents.Append(" mono_runtime_invoke(mmethod->GetNative(), instance, params, &exception);").AppendLine(); + contents.Append(" if (exception)").AppendLine(); + contents.Append(" DebugLog::LogException(exception);").AppendLine(); + contents.Append(" }").AppendLine().AppendLine(); + + // C# event wrapper binding method (binds/unbinds C# wrapper to C++ delegate) + contents.AppendFormat(" static void {0}_ManagedBind(", eventInfo.Name); + if (!eventInfo.IsStatic) + contents.AppendFormat("{0}* obj, ", classTypeNameNative); + contents.Append("bool bind)").AppendLine(); + contents.Append(" {").AppendLine(); + contents.Append(" Function f;").AppendLine(); + if (eventInfo.IsStatic) + contents.AppendFormat(" f.Bind<{0}_ManagedWrapper>();", eventInfo.Name).AppendLine(); + else + contents.AppendFormat(" f.Bind<{1}Internal, &{1}Internal::{0}_ManagedWrapper>(({1}Internal*)obj);", eventInfo.Name, classTypeNameInternal).AppendLine(); + contents.Append(" if (bind)").AppendLine(); + contents.AppendFormat(" {0}{1}.Bind(f);", bindPrefix, eventInfo.Name).AppendLine(); + contents.Append(" else").AppendLine(); + contents.AppendFormat(" {0}{1}.Unbind(f);", bindPrefix, eventInfo.Name).AppendLine(); + contents.Append(" }").AppendLine().AppendLine(); + } // Generic scripting event invoking wrapper (calls scripting code from C++ delegate) CppIncludeFiles.Add("Engine/Scripting/Events.h"); @@ -1551,7 +1571,7 @@ namespace Flax.Build.Bindings // Fields foreach (var fieldInfo in classInfo.Fields) { - if (!useScripting) + if (!useScripting || !useCSharp) continue; if (fieldInfo.Getter != null) GenerateCppWrapperFunction(buildData, contents, classInfo, fieldInfo.Getter, "{0}"); @@ -1568,7 +1588,7 @@ namespace Flax.Build.Bindings // Properties foreach (var propertyInfo in classInfo.Properties) { - if (!useScripting) + if (!useScripting || !useCSharp) continue; if (propertyInfo.Getter != null) GenerateCppWrapperFunction(buildData, contents, classInfo, propertyInfo.Getter); @@ -1579,13 +1599,15 @@ namespace Flax.Build.Bindings // Functions foreach (var functionInfo in classInfo.Functions) { + if (!useCSharp) + continue; if (!useScripting) throw new Exception($"Not supported function {functionInfo.Name} inside non-static and non-scripting class type {classInfo.Name}."); GenerateCppWrapperFunction(buildData, contents, classInfo, functionInfo); } // Interface implementation - if (hasInterface) + if (hasInterface && useCSharp) { foreach (var interfaceInfo in classInfo.Interfaces) { @@ -1612,11 +1634,16 @@ namespace Flax.Build.Bindings { foreach (var eventInfo in classInfo.Events) { - contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{eventInfo.Name}_Bind\", &{eventInfo.Name}_ManagedBind);"); - // Register scripting event binder contents.AppendLine($" ScriptingEvents::EventsTable[Pair({classTypeNameNative}::TypeInitializer, StringView(TEXT(\"{eventInfo.Name}\"), {eventInfo.Name.Length}))] = (void(*)(ScriptingObject*, void*, bool)){classTypeNameInternal}Internal::{eventInfo.Name}_Bind;"); } + } + if (useScripting && useCSharp) + { + foreach (var eventInfo in classInfo.Events) + { + contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{eventInfo.Name}_Bind\", &{eventInfo.Name}_ManagedBind);"); + } foreach (var fieldInfo in classInfo.Fields) { if (fieldInfo.Getter != null) @@ -1720,6 +1747,7 @@ namespace Flax.Build.Bindings var structureTypeNameInternal = structureInfo.NativeName; if (structureInfo.Parent != null && !(structureInfo.Parent is FileInfo)) structureTypeNameInternal = structureInfo.Parent.FullNameNative + '_' + structureTypeNameInternal; + var useCSharp = EngineConfiguration.WithCSharp(buildData.TargetOptions); if (structureInfo.IsAutoSerialization) GenerateCppAutoSerialization(buildData, contents, moduleInfo, structureInfo, structureTypeNameNative); @@ -1786,12 +1814,15 @@ namespace Flax.Build.Bindings contents.AppendLine(" static void InitRuntime()"); contents.AppendLine(" {"); - foreach (var fieldInfo in structureInfo.Fields) + if (useCSharp) { - if (fieldInfo.Getter != null) - contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{fieldInfo.Getter.UniqueName}\", &{fieldInfo.Getter.UniqueName});"); - if (fieldInfo.Setter != null) - contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{fieldInfo.Setter.UniqueName}\", &{fieldInfo.Setter.UniqueName});"); + foreach (var fieldInfo in structureInfo.Fields) + { + if (fieldInfo.Getter != null) + contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{fieldInfo.Getter.UniqueName}\", &{fieldInfo.Getter.UniqueName});"); + if (fieldInfo.Setter != null) + contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{fieldInfo.Setter.UniqueName}\", &{fieldInfo.Setter.UniqueName});"); + } } contents.AppendLine(" }").AppendLine(); @@ -1814,28 +1845,41 @@ namespace Flax.Build.Bindings contents.AppendLine($" *({structureTypeNameNative}*)dst = *({structureTypeNameNative}*)src;"); contents.AppendLine(" }").AppendLine(); - // Boxing structures from native data to managed object - CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h"); - if (!structureInfo.IsPod && !CppUsedNonPodTypes.Contains(structureInfo)) - CppUsedNonPodTypes.Add(structureInfo); - contents.AppendLine(" static MonoObject* Box(void* ptr)"); - contents.AppendLine(" {"); - contents.AppendLine($" MonoObject* managed = mono_object_new(mono_domain_get(), {structureTypeNameNative}::TypeInitializer.GetType().ManagedClass->GetNative());"); - if (structureInfo.IsPod) - contents.AppendLine($" Platform::MemoryCopy(mono_object_unbox(managed), ptr, sizeof({structureTypeNameNative}));"); - else - contents.AppendLine($" *({structureInfo.NativeName}Managed*)mono_object_unbox(managed) = ToManaged(*({structureTypeNameNative}*)ptr);"); - contents.AppendLine(" return managed;"); - contents.AppendLine(" }").AppendLine(); + if (useCSharp) + { + // Boxing structures from native data to managed object + CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h"); + if (!structureInfo.IsPod && !CppUsedNonPodTypes.Contains(structureInfo)) + CppUsedNonPodTypes.Add(structureInfo); + contents.AppendLine(" static MObject* Box(void* ptr)"); + contents.AppendLine(" {"); + contents.AppendLine($" MonoObject* managed = mono_object_new(mono_domain_get(), {structureTypeNameNative}::TypeInitializer.GetType().ManagedClass->GetNative());"); + if (structureInfo.IsPod) + contents.AppendLine($" Platform::MemoryCopy(mono_object_unbox(managed), ptr, sizeof({structureTypeNameNative}));"); + else + contents.AppendLine($" *({structureInfo.NativeName}Managed*)mono_object_unbox(managed) = ToManaged(*({structureTypeNameNative}*)ptr);"); + contents.AppendLine(" return managed;"); + contents.AppendLine(" }").AppendLine(); - // Unboxing structures from managed object to native data - contents.AppendLine(" static void Unbox(void* ptr, MonoObject* managed)"); - contents.AppendLine(" {"); - if (structureInfo.IsPod) - contents.AppendLine($" Platform::MemoryCopy(ptr, mono_object_unbox(managed), sizeof({structureTypeNameNative}));"); + // Unboxing structures from managed object to native data + contents.AppendLine(" static void Unbox(void* ptr, MObject* managed)"); + contents.AppendLine(" {"); + if (structureInfo.IsPod) + contents.AppendLine($" Platform::MemoryCopy(ptr, mono_object_unbox(managed), sizeof({structureTypeNameNative}));"); + else + contents.AppendLine($" *({structureTypeNameNative}*)ptr = ToNative(*({structureInfo.NativeName}Managed*)mono_object_unbox(managed));"); + contents.AppendLine(" }").AppendLine(); + } else - contents.AppendLine($" *({structureTypeNameNative}*)ptr = ToNative(*({structureInfo.NativeName}Managed*)mono_object_unbox(managed));"); - contents.AppendLine(" }").AppendLine(); + { + contents.AppendLine(" static MObject* Box(void* ptr)"); + contents.AppendLine(" {"); + contents.AppendLine(" return nullptr;"); + contents.AppendLine(" }").AppendLine(); + contents.AppendLine(" static void Unbox(void* ptr, MObject* managed)"); + contents.AppendLine(" {"); + contents.AppendLine(" }").AppendLine(); + } // Getter for structure field contents.AppendLine(" static void GetField(void* ptr, const String& name, Variant& value)"); @@ -2060,6 +2104,9 @@ namespace Flax.Build.Bindings CppVariantToTypes.Clear(); CppVariantFromTypes.Clear(); + // Disable C# scripting based on configuration + ScriptingLangInfos[0].Enabled = EngineConfiguration.WithCSharp(buildData.TargetOptions); + contents.AppendLine("// This code was auto-generated. Do not modify it."); contents.AppendLine(); contents.AppendLine("#include \"Engine/Core/Compiler.h\""); @@ -2174,8 +2221,11 @@ namespace Flax.Build.Bindings // Non-POD types CppUsedNonPodTypesList.Clear(); - for (int k = 0; k < CppUsedNonPodTypes.Count; k++) - GenerateCppCppUsedNonPodTypes(buildData, CppUsedNonPodTypes[k]); + if (EngineConfiguration.WithCSharp(buildData.TargetOptions)) + { + for (int k = 0; k < CppUsedNonPodTypes.Count; k++) + GenerateCppCppUsedNonPodTypes(buildData, CppUsedNonPodTypes[k]); + } foreach (var apiType in CppUsedNonPodTypesList) { header.AppendLine(); diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs index 6645bc484..280006170 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Flax.Build.NativeCpp; @@ -34,8 +35,20 @@ namespace Flax.Build.Bindings /// The generated C# file path that contains a API bindings wrapper code to setup the glue code. /// public string GeneratedCSharpFilePath; + + /// + /// The custom data per-scripting language. + /// + public Dictionary CustomScriptingData; } + public delegate void GenerateModuleBindingsDelegate(BuildData buildData, IGrouping binaryModule); + + public delegate void GenerateBinaryModuleBindingsDelegate(BuildData buildData, ModuleInfo moduleInfo, ref BindingsResult bindings); + + public static event GenerateModuleBindingsDelegate GenerateModuleBindings; + public static event GenerateBinaryModuleBindingsDelegate GenerateBinaryModuleBindings; + public static ModuleInfo ParseModule(BuildData buildData, Module module, BuildOptions moduleOptions = null) { if (buildData.ModulesInfo.TryGetValue(module, out var moduleInfo)) @@ -513,7 +526,7 @@ namespace Flax.Build.Bindings buildData.Modules.TryGetValue(moduleInfo.Module, out var moduleBuildInfo); // Ensure that generated files are included into build - if (!moduleBuildInfo.SourceFiles.Contains(bindings.GeneratedCSharpFilePath)) + if (EngineConfiguration.WithCSharp(buildData.TargetOptions) && !moduleBuildInfo.SourceFiles.Contains(bindings.GeneratedCSharpFilePath)) moduleBuildInfo.SourceFiles.Add(bindings.GeneratedCSharpFilePath); } @@ -533,10 +546,12 @@ namespace Flax.Build.Bindings Log.Verbose($"Generating API bindings for {module.Name} ({moduleInfo.Name})"); using (new ProfileEventScope("Cpp")) GenerateCpp(buildData, moduleInfo, ref bindings); - using (new ProfileEventScope("CSharp")) - GenerateCSharp(buildData, moduleInfo, ref bindings); - - // TODO: add support for extending this code and support generating bindings for other scripting languages + if (EngineConfiguration.WithCSharp(buildData.TargetOptions)) + { + using (new ProfileEventScope("CSharp")) + GenerateCSharp(buildData, moduleInfo, ref bindings); + } + GenerateBinaryModuleBindings?.Invoke(buildData, moduleInfo, ref bindings); } } @@ -552,9 +567,11 @@ namespace Flax.Build.Bindings // Generate bindings for binary module Log.Verbose($"Generating binary module bindings for {binaryModule.Key}"); GenerateCpp(buildData, binaryModule); - GenerateCSharp(buildData, binaryModule); - - // TODO: add support for extending this code and support generating bindings for other scripting languages + if (EngineConfiguration.WithCSharp(buildData.TargetOptions)) + { + GenerateCSharp(buildData, binaryModule); + } + GenerateModuleBindings?.Invoke(buildData, binaryModule); } } } diff --git a/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs b/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs index ce39eb3a9..35e923645 100644 --- a/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs +++ b/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs @@ -15,7 +15,7 @@ namespace Flax.Build throw new NotImplementedException("TODO: building C# targets"); } - private static void BuildTargetBindings(RulesAssembly rules, TaskGraph graph, BuildData buildData) + private static void BuildTargetBindings(TaskGraph graph, BuildData buildData) { var workspaceRoot = buildData.TargetOptions.WorkingDirectory; var args = new List(); diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs index 494288a05..183d44e7a 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs @@ -167,6 +167,7 @@ namespace Flax.Build public static event Action PreBuild; public static event Action PostBuild; + public static event Action BuildBindings; /// /// Collects the modules required by the given target to build (includes dependencies). @@ -226,6 +227,20 @@ namespace Flax.Build return buildData.Modules; } + private static void OnBuildBindings(BuildData buildData, TaskGraph graph) + { + if (buildData.Target.IsPreBuilt) + return; + using (new ProfileEventScope("BuildBindings")) + { + if (EngineConfiguration.WithCSharp(buildData.TargetOptions)) + { + BuildTargetBindings(graph, buildData); + } + BuildBindings?.Invoke(graph, buildData); + } + } + private static void LinkNativeBinary(BuildData buildData, BuildOptions buildOptions, string outputPath) { using (new ProfileEventScope("LinkNativeBinary")) @@ -794,13 +809,7 @@ namespace Flax.Build } // Build scripting API bindings - using (new ProfileEventScope("BuildBindings")) - { - if (!buildData.Target.IsPreBuilt) - { - BuildTargetBindings(rules, graph, buildData); - } - } + OnBuildBindings(buildData, graph); // Link modules into a target var outputTargetFilePath = target.GetOutputFilePath(targetBuildOptions); @@ -835,7 +844,7 @@ namespace Flax.Build var binaryModuleInfo = new BuildTargetBinaryModuleInfo { Name = binaryModule.Key, - ManagedPath = Path.Combine(outputPath, binaryModule.Key + ".CSharp.dll"), + ManagedPath = EngineConfiguration.WithCSharp(targetBuildOptions) ? Path.Combine(outputPath, binaryModule.Key + ".CSharp.dll") : string.Empty, }; switch (target.LinkType) { @@ -1069,11 +1078,7 @@ namespace Flax.Build } // Build scripting API bindings - using (new ProfileEventScope("BuildBindings")) - { - if (!buildData.Target.IsPreBuilt) - BuildTargetBindings(rules, graph, buildData); - } + OnBuildBindings(buildData, graph); // Link modules into a target var outputTargetFilePath = target.GetOutputFilePath(targetBuildOptions); @@ -1099,7 +1104,7 @@ namespace Flax.Build var binaryModuleInfo = new BuildTargetBinaryModuleInfo { Name = binaryModule.Key, - ManagedPath = Path.Combine(outputPath, binaryModule.Key + ".CSharp.dll"), + ManagedPath = EngineConfiguration.WithCSharp(targetBuildOptions) ? Path.Combine(outputPath, binaryModule.Key + ".CSharp.dll") : string.Empty, }; binaryModuleInfo.NativePathProcessed = string.Empty; diff --git a/Source/Tools/Flax.Build/Build/Plugins/VisualScriptingPlugin.cs b/Source/Tools/Flax.Build/Build/Plugins/VisualScriptingPlugin.cs index c22812960..ca3052656 100644 --- a/Source/Tools/Flax.Build/Build/Plugins/VisualScriptingPlugin.cs +++ b/Source/Tools/Flax.Build/Build/Plugins/VisualScriptingPlugin.cs @@ -17,7 +17,11 @@ namespace Flax.Build.Plugins base.Init(); BindingsGenerator.GenerateCppScriptWrapperFunction += OnGenerateCppScriptWrapperFunction; - BindingsGenerator.CppScriptObjectVirtualWrapperMethodsPostfixes.Add("_VisualScriptWrapper"); + BindingsGenerator.ScriptingLangInfos.Add(new BindingsGenerator.ScriptingLangInfo + { + Enabled = true, + VirtualWrapperMethodsPostfix = "_VisualScriptWrapper", + }); } private void OnGenerateCppScriptWrapperFunction(Builder.BuildData buildData, VirtualClassInfo classInfo, FunctionInfo functionInfo, int scriptVTableSize, int scriptVTableIndex, StringBuilder contents) diff --git a/Source/Tools/Flax.Build/Build/ProjectTarget.cs b/Source/Tools/Flax.Build/Build/ProjectTarget.cs index 790452b34..4aa30fe03 100644 --- a/Source/Tools/Flax.Build/Build/ProjectTarget.cs +++ b/Source/Tools/Flax.Build/Build/ProjectTarget.cs @@ -67,6 +67,12 @@ namespace Flax.Build options.CompileEnv.IncludePaths.Add(Path.Combine(Project.ProjectFolderPath, "Source")); options.LinkEnv.LibraryPaths.Add(depsRoot); + // Ensure to propagate no-C# scripting define to the whole codebase + if (!EngineConfiguration.WithCSharp(options)) + { + options.CompileEnv.PreprocessorDefinitions.Add("COMPILE_WITHOUT_CSHARP"); + } + // Add include paths for referenced projects sources foreach (var reference in Project.References) { diff --git a/Source/Tools/Flax.Build/Configuration.cs b/Source/Tools/Flax.Build/Configuration.cs index bd9785d35..8ad0e2fd6 100644 --- a/Source/Tools/Flax.Build/Configuration.cs +++ b/Source/Tools/Flax.Build/Configuration.cs @@ -212,4 +212,21 @@ namespace Flax.Build /// public static List CustomDefines = new List(); } + + /// + /// The engine configuration options. + /// + public static partial class EngineConfiguration + { + /// + /// True if managed C# scripting should be enabled, otherwise false. Engine without C# is partially supported and can be used when porting to a new platform before implementing C# runtime on it. + /// + [CommandLine("useCSharp", "0 to disable C# support in build")] + public static bool UseCSharp = true; + + public static bool WithCSharp(NativeCpp.BuildOptions options) + { + return UseCSharp || options.Target.IsEditor; + } + } } diff --git a/Source/Tools/Flax.Build/Program.cs b/Source/Tools/Flax.Build/Program.cs index 04d8a40bf..8d8667af9 100644 --- a/Source/Tools/Flax.Build/Program.cs +++ b/Source/Tools/Flax.Build/Program.cs @@ -38,6 +38,7 @@ namespace Flax.Build { // Setup CommandLine.Configure(typeof(Configuration)); + CommandLine.Configure(typeof(EngineConfiguration)); foreach (var option in CommandLine.GetOptions()) { if (option.Name.Length > 1 && option.Name[0] == 'D')