diff --git a/Plugins/UnrealSharp/Source/UnrealSharp/Private/Misc/UnrealFunctionInvocation.cpp b/Plugins/UnrealSharp/Source/UnrealSharp/Private/Misc/UnrealFunctionInvocation.cpp index 9927336..8f95d23 100644 --- a/Plugins/UnrealSharp/Source/UnrealSharp/Private/Misc/UnrealFunctionInvocation.cpp +++ b/Plugins/UnrealSharp/Source/UnrealSharp/Private/Misc/UnrealFunctionInvocation.cpp @@ -25,6 +25,8 @@ */ #include "Misc/UnrealFunctionInvocation.h" +#include "Misc/UnrealSharpLog.h" + namespace UnrealSharp { FUnrealFunctionInvocation::FUnrealFunctionInvocation() @@ -79,8 +81,10 @@ namespace UnrealSharp checkf(Function != nullptr, TEXT("Failed bind function %s in class %s"), InFunctionName, *InClass->GetPathName()); } - void FUnrealFunctionInvocation::InitializeParameterBuffer(void* InParameterBuffer, int /*InParameterBufferSize*/) const + void FUnrealFunctionInvocation::InitializeParameterBuffer(void* InParameterBuffer, int InParameterBufferSize) const { + US_UNREFERENCED_PARAMETER(InParameterBufferSize); + check(Function); check(InParameterBuffer); @@ -94,8 +98,10 @@ namespace UnrealSharp } } - void FUnrealFunctionInvocation::UnInitializeParameterBuffer(void* InParameterBuffer, int /*InParameterBufferSize*/) const + void FUnrealFunctionInvocation::UnInitializeParameterBuffer(void* InParameterBuffer, int InParameterBufferSize) const { + US_UNREFERENCED_PARAMETER(InParameterBufferSize); + check(Function); check(InParameterBuffer); diff --git a/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoProfilerService.cpp b/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoProfilerService.cpp new file mode 100644 index 0000000..2ed4535 --- /dev/null +++ b/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoProfilerService.cpp @@ -0,0 +1,60 @@ +/* + MIT License + + Copyright (c) 2024 UnrealSharp + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Project URL: https://github.com/bodong1987/UnrealSharp +*/ +#include "MonoProfilerService.h" + +#if WITH_MONO +#include "Networking.h" +#include "Sockets.h" +#include "SocketSubsystem.h" + +namespace UnrealSharp::Mono +{ + FMonoProfilerService::FMonoProfilerService(int InPort) : + DefaultPort(InPort) + { + FIPv4Address IPAddress; + FIPv4Address::Parse(TEXT("127.0.0.1"), IPAddress); + + const FIPv4Endpoint Endpoint(IPAddress, DefaultPort); + + ListenerSocket = FTcpSocketBuilder(TEXT("TcpListener")) + .AsReusable() + .BoundToEndpoint(Endpoint) + .Listening(8); + } + + FMonoProfilerService::~FMonoProfilerService() + { + if(ListenerSocket) + { + ListenerSocket->Close(); + + ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ListenerSocket); + ListenerSocket = nullptr; + } + } +} +#endif diff --git a/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoProfilerService.h b/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoProfilerService.h new file mode 100644 index 0000000..a9b91ab --- /dev/null +++ b/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoProfilerService.h @@ -0,0 +1,45 @@ +/* + MIT License + + Copyright (c) 2024 UnrealSharp + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Project URL: https://github.com/bodong1987/UnrealSharp +*/ +#pragma once + +#include "CoreMinimal.h" + +#if WITH_MONO +namespace UnrealSharp::Mono +{ + class FMonoProfilerService + { + public: + FMonoProfilerService(int InPort); + ~FMonoProfilerService(); + + private: + FSocket* ListenerSocket = nullptr; + int DefaultPort = 55987; + }; +} +#endif + diff --git a/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoPropertyMarshaller.cpp b/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoPropertyMarshaller.cpp index 8a69657..3924bd8 100644 --- a/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoPropertyMarshaller.cpp +++ b/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoPropertyMarshaller.cpp @@ -273,7 +273,7 @@ namespace UnrealSharp::Mono const FName* NamePtr = (const FName*)InParameters.InputAddress; // NOLINT FName* TempBuffer = (FName*)(InParameters.InputReferenceAddress + 1); // NOLINT - checkSlow((SIZE_T)(void*)TempBuffer - (SIZE_T)(void*)InParameters.InputReferenceAddress == sizeof(void*)); + checkSlow(reinterpret_cast(static_cast(TempBuffer)) - reinterpret_cast(static_cast(InParameters.InputReferenceAddress)) == sizeof(void*)); // For special processing of this type, we obtain more temporary space through GetTempParameterBufferSize, // and then store the data in the extra space. @@ -316,7 +316,7 @@ namespace UnrealSharp::Mono const FString Text = TextPtr->ToString(); FCSharpText* TempBuffer = (FCSharpText*)(InParameters.InputReferenceAddress + 1); // NOLINT - checkSlow((SIZE_T)(void*)TempBuffer - (SIZE_T)(void*)InParameters.InputReferenceAddress == sizeof(void*)); + checkSlow(reinterpret_cast(TempBuffer) - reinterpret_cast(InParameters.InputReferenceAddress) == sizeof(void*)); // For special processing of this type, we obtain more temporary space through GetTempParameterBufferSize, // and then store the data in the extra space. @@ -420,7 +420,7 @@ namespace UnrealSharp::Mono const UClass** AddressOfClassPointer = (const UClass**)InParameters.InputAddress; // NOLINT FCSharpSubclassOf* TempBuffer = (FCSharpSubclassOf*)(InParameters.InputReferenceAddress + 1); // NOLINT - checkSlow((SIZE_T)(void*)TempBuffer - (SIZE_T)(void*)InParameters.InputReferenceAddress == sizeof(void*)); + checkSlow(reinterpret_cast(TempBuffer) - reinterpret_cast(InParameters.InputReferenceAddress) == sizeof(void*)); // For special processing of this type, we obtain more temporary space through GetTempParameterBufferSize, // and then store the data in the extra space. diff --git a/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoRuntime.cpp b/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoRuntime.cpp index 9ec3833..2bbaf1a 100644 --- a/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoRuntime.cpp +++ b/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoRuntime.cpp @@ -24,13 +24,14 @@ Project URL: https://github.com/bodong1987/UnrealSharp */ #include "MonoRuntime/MonoRuntime.h" -#include "MonoRuntime/MonoInteropUtils.h" #include "Classes/UnrealSharpSettings.h" #include "Misc/UnrealSharpLog.h" #include "Misc/ScopedExit.h" #include "Misc/UnrealSharpPaths.h" #if WITH_MONO +#include "MonoProfilerService.h" +#include "MonoRuntime/MonoInteropUtils.h" #include "MonoRuntime/MonoMethod.h" #include "MonoRuntime/MonoType.h" #include "MonoRuntime/MonoMethodInvocation.h" @@ -335,6 +336,8 @@ namespace UnrealSharp::Mono mono_jit_parse_options(sizeof(Options)/sizeof(Options[0]), (char**)Options); // NOLINT mono_debug_init(MONO_DEBUG_FORMAT_MONO); + MonoProfiler.Reset(new FMonoProfilerService(Settings->FakedMonoProfilerPort)); + bIsDebuggerAvailable = true; } } diff --git a/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoRuntime.h b/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoRuntime.h index 8422aaa..f351b81 100644 --- a/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoRuntime.h +++ b/Plugins/UnrealSharp/Source/UnrealSharp/Private/MonoRuntime/MonoRuntime.h @@ -32,6 +32,7 @@ namespace UnrealSharp::Mono { + class FMonoProfilerService; class FMonoObjectTable; class FPropertyMarshallerCollection; @@ -107,6 +108,7 @@ namespace UnrealSharp::Mono TMap AssemblyCaches; TUniquePtr MarshallerCollectionPtr; + TUniquePtr MonoProfiler; bool bUseTempCoreClrLibrary = false; static bool bIsDebuggerAvailable; diff --git a/Plugins/UnrealSharp/Source/UnrealSharp/Private/UnrealFunctionInvokeRedirector.cpp b/Plugins/UnrealSharp/Source/UnrealSharp/Private/UnrealFunctionInvokeRedirector.cpp index 67ed699..44d2bd4 100644 --- a/Plugins/UnrealSharp/Source/UnrealSharp/Private/UnrealFunctionInvokeRedirector.cpp +++ b/Plugins/UnrealSharp/Source/UnrealSharp/Private/UnrealFunctionInvokeRedirector.cpp @@ -195,7 +195,7 @@ namespace UnrealSharp { if (const auto& [Property, MarshallerPtr] = PropertyQueue[Index]; MarshallerPtr && MarshallerPtr->bPassByReference) { - checkSlow(MarshallerPtr->Property == PropertyInfo.Property); + checkSlow(MarshallerPtr->Property == Property); void** UnrealInternalDataPointerAddress = GetUnrealParameterReferencePointerAddress(InUnrealParameterReferencePointers, Index); void** InteropTempDataPointerAddress = GetTempParameterPointerAddress(InTempInteropParameterPointers, MarshallerPtr->OffsetInTempParameterBuffer); diff --git a/Plugins/UnrealSharp/Source/UnrealSharp/Public/Classes/UnrealSharpSettings.h b/Plugins/UnrealSharp/Source/UnrealSharp/Public/Classes/UnrealSharpSettings.h index ece6208..b756019 100644 --- a/Plugins/UnrealSharp/Source/UnrealSharp/Public/Classes/UnrealSharpSettings.h +++ b/Plugins/UnrealSharp/Source/UnrealSharp/Public/Classes/UnrealSharpSettings.h @@ -77,6 +77,14 @@ class UNREALSHARP_API UUnrealSharpSettings : public UDeveloperSettings UPROPERTY(EditAnywhere, config, Category = "Debugger|Mono") float DelayMonoStartTimeWhenWaitDebugger = 1.0f; + /* + * After a certain updated version of Visual Studio for Unity, a Profiler port must exist to support debugging using Visual Studio. + * Therefore, this port is used to fake a Mono Profiler listening port. + * @reference https://www.cnblogs.com/bodong/p/17962564 + */ + UPROPERTY(EditAnywhere, config, Category = "Debugger|Mono") + int FakedMonoProfilerPort = 55987; + /* * If this option is turned on, when using the mono runtime, * it will try to output some information inside the mono debugger to the specified file, diff --git a/Plugins/UnrealSharp/Source/UnrealSharp/UnrealSharp.Build.cs b/Plugins/UnrealSharp/Source/UnrealSharp/UnrealSharp.Build.cs index 2de5f64..3c33734 100644 --- a/Plugins/UnrealSharp/Source/UnrealSharp/UnrealSharp.Build.cs +++ b/Plugins/UnrealSharp/Source/UnrealSharp/UnrealSharp.Build.cs @@ -76,7 +76,9 @@ public UnrealSharp(ReadOnlyTargetRules Target) : base(Target) "Core", "CoreUObject", "Engine", - "DeveloperSettings" + "DeveloperSettings", + "Sockets", + "Networking" // ... add other public dependencies that you statically link with here ... } ); diff --git a/Plugins/UnrealSharp/UnrealSharp.uplugin b/Plugins/UnrealSharp/UnrealSharp.uplugin index 918b1a7..99fa9ae 100644 --- a/Plugins/UnrealSharp/UnrealSharp.uplugin +++ b/Plugins/UnrealSharp/UnrealSharp.uplugin @@ -1,7 +1,7 @@ { "FileVersion": 3, "Version": 1, - "VersionName": "1.2.0.0", + "VersionName": "1.2.0.1", "FriendlyName": "UnrealSharp", "Description": "A plug-in that allows you to develop in Unreal Engine 5 with C# 12 and .NET 8.0", "Category": "Programming", diff --git a/Plugins/UnrealSharpTests/UnrealSharpTests.uplugin b/Plugins/UnrealSharpTests/UnrealSharpTests.uplugin index 1a54945..dfcfdf1 100644 --- a/Plugins/UnrealSharpTests/UnrealSharpTests.uplugin +++ b/Plugins/UnrealSharpTests/UnrealSharpTests.uplugin @@ -1,7 +1,7 @@ { "FileVersion": 3, "Version": 1, - "VersionName": "1.2.0.0", + "VersionName": "1.2.0.1", "FriendlyName": "UnrealSharpTests", "Description": "Plugin for UnrealSharp testing", "Category": "Programming",