This commit is contained in:
2026-01-04 02:57:02 +02:00
parent 7088ce8742
commit 1b8e25cb86
8 changed files with 235 additions and 65 deletions

View File

@@ -269,7 +269,7 @@ namespace FlaxEngine
internal static partial bool Internal_HasConnection(ref AnimationGraph.CustomNode.Context context, int boxId);
[LibraryImport("FlaxEngine", EntryPoint = "AnimGraphInternal_GetInputValue")]
[return: MarshalUsing(typeof(FlaxEngine.Interop.ManagedHandleMarshaller))]
[return: MarshalUsing(typeof(FlaxEngine.Interop.AsManagedHandleMarshaller))]
internal static partial object Internal_GetInputValue(ref AnimationGraph.CustomNode.Context context, int boxId);
[LibraryImport("FlaxEngine", EntryPoint = "AnimGraphInternal_GetOutputImpulseData")]

View File

@@ -17,16 +17,16 @@ namespace FlaxEngine.Interop
#if FLAX_EDITOR
[HideInEditor]
#endif
[CustomMarshaller(typeof(object), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedHandleMarshaller.ManagedToNativeState))]
[CustomMarshaller(typeof(object), MarshalMode.UnmanagedToManagedOut, typeof(ManagedHandleMarshaller.ManagedToNativeState))]
[CustomMarshaller(typeof(object), MarshalMode.ElementIn, typeof(ManagedHandleMarshaller.ManagedToNative))]
[CustomMarshaller(typeof(object), MarshalMode.ManagedToUnmanagedOut, typeof(ManagedHandleMarshaller.NativeToManaged))]
[CustomMarshaller(typeof(object), MarshalMode.UnmanagedToManagedIn, typeof(ManagedHandleMarshaller.NativeToManaged))]
[CustomMarshaller(typeof(object), MarshalMode.ElementOut, typeof(ManagedHandleMarshaller.NativeToManaged))]
[CustomMarshaller(typeof(object), MarshalMode.ManagedToUnmanagedRef, typeof(ManagedHandleMarshaller.Bidirectional))]
[CustomMarshaller(typeof(object), MarshalMode.UnmanagedToManagedRef, typeof(ManagedHandleMarshaller.Bidirectional))]
[CustomMarshaller(typeof(object), MarshalMode.ElementRef, typeof(ManagedHandleMarshaller))]
public static class ManagedHandleMarshaller
[CustomMarshaller(typeof(object), MarshalMode.ManagedToUnmanagedIn, typeof(AsManagedHandleMarshaller.ManagedToNativeState))]
[CustomMarshaller(typeof(object), MarshalMode.UnmanagedToManagedOut, typeof(AsManagedHandleMarshaller.ManagedToNativeState))]
[CustomMarshaller(typeof(object), MarshalMode.ElementIn, typeof(AsManagedHandleMarshaller.ManagedToNative))]
[CustomMarshaller(typeof(object), MarshalMode.ManagedToUnmanagedOut, typeof(AsManagedHandleMarshaller.NativeToManaged))]
[CustomMarshaller(typeof(object), MarshalMode.UnmanagedToManagedIn, typeof(AsManagedHandleMarshaller.NativeToManaged))]
[CustomMarshaller(typeof(object), MarshalMode.ElementOut, typeof(AsManagedHandleMarshaller.NativeToManaged))]
[CustomMarshaller(typeof(object), MarshalMode.ManagedToUnmanagedRef, typeof(AsManagedHandleMarshaller.Bidirectional))]
[CustomMarshaller(typeof(object), MarshalMode.UnmanagedToManagedRef, typeof(AsManagedHandleMarshaller.Bidirectional))]
[CustomMarshaller(typeof(object), MarshalMode.ElementRef, typeof(AsManagedHandleMarshaller))]
public static class AsManagedHandleMarshaller
{
#if FLAX_EDITOR
[HideInEditor]
@@ -132,7 +132,7 @@ namespace FlaxEngine.Interop
public IntPtr ToUnmanaged()
{
unmanaged = ManagedHandleMarshaller.ToNative(managed);
unmanaged = AsManagedHandleMarshaller.ToNative(managed);
return unmanaged;
}
@@ -143,7 +143,7 @@ namespace FlaxEngine.Interop
public object ToManaged()
{
managed = ManagedHandleMarshaller.ToManaged(unmanaged);
managed = AsManagedHandleMarshaller.ToManaged(unmanaged);
unmanaged = IntPtr.Zero;
return managed;
}
@@ -177,7 +177,7 @@ namespace FlaxEngine.Interop
[CustomMarshaller(typeof(Type), MarshalMode.Default, typeof(SystemTypeMarshaller))]
public static class SystemTypeMarshaller
{
public static Type ConvertToManaged(IntPtr unmanaged) => unmanaged != IntPtr.Zero ? Unsafe.As<FlaxEngine.Interop.NativeInterop.TypeHolder>(ManagedHandleMarshaller.ConvertToManaged(unmanaged)).type : null;
public static Type ConvertToManaged(IntPtr unmanaged) => unmanaged != IntPtr.Zero ? Unsafe.As<FlaxEngine.Interop.NativeInterop.TypeHolder>(AsManagedHandleMarshaller.ConvertToManaged(unmanaged)).type : null;
public static IntPtr ConvertToUnmanaged(Type managed)
{
@@ -199,9 +199,9 @@ namespace FlaxEngine.Interop
[CustomMarshaller(typeof(Exception), MarshalMode.Default, typeof(ExceptionMarshaller))]
public static class ExceptionMarshaller
{
public static Exception ConvertToManaged(IntPtr unmanaged) => Unsafe.As<Exception>(ManagedHandleMarshaller.ConvertToManaged(unmanaged));
public static IntPtr ConvertToUnmanaged(Exception managed) => ManagedHandleMarshaller.ConvertToUnmanaged(managed);
public static void Free(IntPtr unmanaged) => ManagedHandleMarshaller.Free(unmanaged);
public static Exception ConvertToManaged(IntPtr unmanaged) => Unsafe.As<Exception>(AsManagedHandleMarshaller.ConvertToManaged(unmanaged));
public static IntPtr ConvertToUnmanaged(Exception managed) => AsManagedHandleMarshaller.ConvertToUnmanaged(managed);
public static void Free(IntPtr unmanaged) => AsManagedHandleMarshaller.Free(unmanaged);
}
#if FLAX_EDITOR
@@ -225,9 +225,9 @@ namespace FlaxEngine.Interop
[CustomMarshaller(typeof(CultureInfo), MarshalMode.Default, typeof(CultureInfoMarshaller))]
public static class CultureInfoMarshaller
{
public static CultureInfo ConvertToManaged(IntPtr unmanaged) => Unsafe.As<CultureInfo>(ManagedHandleMarshaller.ConvertToManaged(unmanaged));
public static IntPtr ConvertToUnmanaged(CultureInfo managed) => ManagedHandleMarshaller.ConvertToUnmanaged(managed);
public static void Free(IntPtr unmanaged) => ManagedHandleMarshaller.Free(unmanaged);
public static CultureInfo ConvertToManaged(IntPtr unmanaged) => Unsafe.As<CultureInfo>(AsManagedHandleMarshaller.ConvertToManaged(unmanaged));
public static IntPtr ConvertToUnmanaged(CultureInfo managed) => AsManagedHandleMarshaller.ConvertToUnmanaged(managed);
public static void Free(IntPtr unmanaged) => AsManagedHandleMarshaller.Free(unmanaged);
}
#if FLAX_EDITOR
@@ -236,9 +236,9 @@ namespace FlaxEngine.Interop
[CustomMarshaller(typeof(Version), MarshalMode.Default, typeof(VersionMarshaller))]
public static class VersionMarshaller
{
public static Version ConvertToManaged(IntPtr unmanaged) => Unsafe.As<Version>(ManagedHandleMarshaller.ConvertToManaged(unmanaged));
public static IntPtr ConvertToUnmanaged(Version managed) => ManagedHandleMarshaller.ConvertToUnmanaged(managed);
public static void Free(IntPtr unmanaged) => ManagedHandleMarshaller.Free(unmanaged);
public static Version ConvertToManaged(IntPtr unmanaged) => Unsafe.As<Version>(AsManagedHandleMarshaller.ConvertToManaged(unmanaged));
public static IntPtr ConvertToUnmanaged(Version managed) => AsManagedHandleMarshaller.ConvertToUnmanaged(managed);
public static void Free(IntPtr unmanaged) => AsManagedHandleMarshaller.Free(unmanaged);
}
#if FLAX_EDITOR

View File

@@ -785,7 +785,7 @@ namespace FlaxEngine.Interop
for (int i = 0; i < numParams; i++)
{
IntPtr nativePtr = Unsafe.Read<IntPtr>((IntPtr.Add(paramPtr, sizeof(IntPtr) * i)).ToPointer());
methodParameters[i] = MarshalToManaged(nativePtr, methodHolder.parameterTypes[i]);
methodParameters[i] = MarshalToManaged2(nativePtr, methodHolder.parameterTypes[i]);
}
try

View File

@@ -19,6 +19,8 @@ using System.IO;
using System.Text;
using System.Threading;
using System.Buffers;
using System.Runtime.InteropServices.Marshalling;
using FlaxEngine.Utilities;
namespace FlaxEngine.Interop
{
@@ -410,6 +412,164 @@ namespace FlaxEngine.Interop
internal static ConcurrentDictionary<Type, MarshalToNativeDelegate> toNativeMarshallers = new ConcurrentDictionary<Type, MarshalToNativeDelegate>(1, 3);
internal static ConcurrentDictionary<Type, MarshalToNativeFieldDelegate> toNativeFieldMarshallers = new ConcurrentDictionary<Type, MarshalToNativeFieldDelegate>(1, 3);
internal static ConcurrentDictionary<Type, (Type, Func<object, object>)> _marshallers = new(1, 3);
internal static object MarshalToManaged2(IntPtr nativePtr, Type type)
{
static MarshalToManagedDelegate Factory(Type type)
{
Type marshalType = type;
if (marshalType.IsByRef)
marshalType = marshalType.GetElementType();
else if (marshalType.IsPointer)
marshalType = typeof(IntPtr);
MethodInfo method = typeof(MarshalHelper<>).MakeGenericType(marshalType).GetMethod(nameof(MarshalHelper<ReferenceTypePlaceholder>.ToManagedWrapper), BindingFlags.Static | BindingFlags.NonPublic);
return method.CreateDelegate<MarshalToManagedDelegate>();
}
static Type GetCustomMarshaller(Type type)
{
if (type == typeof(bool))
return typeof(BooleanMarshaller);
else if (type.IsArray)
return null;
Type marshallerType = type.GetCustomAttribute<NativeMarshallingAttribute>()?.NativeType;
//if (marshallerType == null && marshallerType != type)
// marshallerType = type.GetCustomAttribute<NativeMarshallingAttribute>()?.NativeType;
return marshallerType;
}
static (Type, Func<object, object>) Factory2(Type type)
{
Type marshalType = type;
if (marshalType.IsByRef)
marshalType = marshalType.GetElementType();
else if (marshalType == typeof(byte*) || marshalType == typeof(char*))
{
}
else if (marshalType.IsPointer)
marshalType = typeof(IntPtr);
Type marshallerType = GetCustomMarshaller(marshalType);
if (marshalType.IsArray)
{
Type elementType = marshalType.GetElementType();
Type elementMarshallerType = GetCustomMarshaller(elementType);
if (elementMarshallerType == null)
{
}
else
{
MethodInfo method2 = elementMarshallerType.GetMethod("ConvertToManaged", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var elementInternalType = method2.GetParameters()[0].ParameterType;
var types2 = new Type[] { elementType, elementInternalType };
marshallerType = typeof(NativeArrayMarshaller<,>).MakeGenericType(types2);
}
}
if (marshallerType == null)
{
if (marshalType == typeof(IntPtr))
{
Func<object, object> func = (obj) => obj;
return (typeof(IntPtr), func);
}
else if (marshalType == typeof(ManagedHandle))
{
Func<object, object> func = (obj) => ManagedHandle.FromIntPtr((IntPtr)obj);
return (typeof(IntPtr), func);
}
}
if (marshallerType == null)
return (null, null);
MethodInfo method = marshallerType.GetMethod("ConvertToManaged", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (method == null)
{
// [CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.ManagedToUnmanagedOut, typeof(NativeArrayMarshaller<,>.NativeToManaged))]
// [CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.UnmanagedToManagedIn, typeof(NativeArrayMarshaller<,>.NativeToManaged))]
var customMarshallerAttributes = marshallerType.GetCustomAttributes<CustomMarshallerAttribute>();
foreach (var attrib in customMarshallerAttributes)
{
if (attrib.MarshalMode == MarshalMode.ManagedToUnmanagedOut)
{
var asdf = typeof(NativeArrayMarshaller<,>.NativeToManaged);
marshallerType = attrib.MarshallerType;
//method = marshallerType.GetMethod("ConvertToManaged", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
}
}
return (null, null);
}
var internalType = method.GetParameters()[0].ParameterType;
var types = new Type[] { marshalType, internalType };
var convertDelegate = method.CreateDelegate(typeof(ToManagedDelegate<,>).MakeGenericType(types));
if (internalType.IsStructure())
{
Func<object, object> func =
(obj) => convertDelegate.DynamicInvoke(obj);
return (internalType, func);
}
else
{
Func<object, object> func =
(obj) => convertDelegate.DynamicInvoke(obj);
return (internalType, func);
}
}
var type2 = type.IsByRef ? type.GetElementType() : type;
if (!_marshallers.TryGetValue(type, out var marsh))
marsh = _marshallers.GetOrAdd(type, Factory2);
if (!toManagedMarshallers.TryGetValue(type, out var deleg))
deleg = toManagedMarshallers.GetOrAdd(type, Factory);
if (marsh.Item2 != null)
{
object conv1 = deleg(nativePtr, type.IsByRef && false);
if (type.IsByRef && marsh.Item1 == typeof(IntPtr))
nativePtr = Unsafe.Read<IntPtr>(nativePtr.ToPointer());
object value = marsh.Item1 == typeof(IntPtr) ? nativePtr : Marshal.PtrToStructure(nativePtr, marsh.Item1);//Unsafe.Read<byte>(nativePtr.ToPointer());
object conv2 = marsh.Item2(value);
if (conv1 is null && conv2 is null)
{ }
else if (!conv1.Equals(conv2))
Assert.IsTrue(conv1.Equals(conv2));
return conv2;
}
else if (type2 == typeof(bool))
{
//object conv1 = deleg(nativePtr, type.IsByRef && false);
byte value = Unsafe.Read<byte>(nativePtr.ToPointer());
object conv2 = BooleanMarshaller.ConvertToManaged(value);
//Assert.IsTrue(conv1.Equals(conv2));
return conv2;
}
else if (type2 == typeof(ManagedHandle))
{
//ManagedHandle conv1 = (ManagedHandle)deleg(nativePtr, type.IsByRef && false);
ManagedHandle conv2 = ManagedHandle.FromIntPtr(nativePtr);
//Assert.IsTrue(conv1.Equals(conv2));
return conv2;
}
else if (type2 == typeof(int) || type2.IsEnum ||
type2 == typeof(IntPtr) || type2 == typeof(Float2) || type2 == typeof(Float3) || type2 == typeof(Guid))
{
}
else
{
}
return deleg(nativePtr, type.IsByRef && false);
}
internal static object MarshalToManaged(IntPtr nativePtr, Type type)
{
static MarshalToManagedDelegate Factory(Type type)
@@ -583,9 +743,6 @@ namespace FlaxEngine.Interop
MethodInfo toManagedFieldMethod;
MethodInfo toNativeFieldMethod;
if (fieldType == typeof(string))
fieldType = fieldType;
if (fieldType == typeof(SoftTypeReference))
{
if (type.IsValueType)
@@ -1409,12 +1566,6 @@ namespace FlaxEngine.Interop
var offsets = MarshalHelper<T>.marshallableFieldOffsets;
var marshallers = MarshalHelper<T>.toNativeFieldMarshallers;
for (int i = 1; i < offsets.Length; i++)
{
if (offsets[i - 1] > offsets[i])
fieldPtr = fieldPtr;
}
for (int i = 0; i < fields.Length; i++)
{
marshallers[i](fields[i], offsets[i], ref managedValue, nativePtr, out int fieldSize);

View File

@@ -37,7 +37,7 @@ DEFINE_INTERNAL_CALL(MObject*) UtilsInternal_ExtractArrayFromList(MObject* obj)
//#if USE_NETCORE
//APgI_TYPEDEF() typedef MString* ManagedString;
API_TYPEDEF() typedef String* ManagedString;
API_TYPEDEF() typedef const String& ManagedString;
//#endif
DEFINE_INTERNAL_CALL(void) PlatformInternal_MemoryCopy(void* dst, const void* src, uint64 size)
@@ -58,11 +58,14 @@ DEFINE_INTERNAL_CALL(int32) PlatformInternal_MemoryCompare(const void* buf1, con
DEFINE_INTERNAL_CALL(void) DebugLogHandlerInternal_LogWrite(LogType level, ManagedString msgObj)
{
#if LOG_ENABLE
#if USE_NETCORE
if (msgObj.IsEmpty())
return;
StringView msg(msgObj);
#else
if (msgObj == nullptr)
return;
#if USE_NETCORE
StringView msg(*msgObj);
#else
StringView msg;
MUtils::ToString(msgObj, msg);
#endif
@@ -73,11 +76,15 @@ DEFINE_INTERNAL_CALL(void) DebugLogHandlerInternal_LogWrite(LogType level, Manag
DEFINE_INTERNAL_CALL(void) DebugLogHandlerInternal_Log(LogType level, ManagedString msgObj, ScriptingObject* obj, ManagedString stackTrace)
{
#if LOG_ENABLE
#if USE_NETCORE
if (msgObj.IsEmpty())
return;
StringView msg(msgObj);
#else
if (msgObj == nullptr)
return;
#if USE_NETCORE
StringView msg(*msgObj);
#else
// Get info
StringView msg;
MUtils::ToString(msgObj, msg);
@@ -135,11 +142,13 @@ namespace
DEFINE_INTERNAL_CALL(void) ProfilerInternal_BeginEvent(ManagedString nameObj)
{
#if COMPILE_WITH_PROFILER
#if USE_NETCORE
if (nameObj.IsEmpty())
return;
StringView name(nameObj);
#else
if (nameObj == nullptr)
return;
#if USE_NETCORE
StringView name(*nameObj);
#else
StringView name;
MUtils::ToString(nameObj, name);
#endif
@@ -198,10 +207,12 @@ DEFINE_INTERNAL_CALL(void) ProfilerInternal_BeginEventGPU(ManagedString nameObj)
{
#if COMPILE_WITH_PROFILER
#if USE_NETCORE
if (nameObj.IsEmpty())
return;
const StringView nameChars(nameObj);
#else
if (nameObj == nullptr)
return;
const StringView nameChars(*nameObj);
#else
const StringView nameChars = MCore::String::GetChars(nameObj);
#endif
const auto index = ProfilerGPU::BeginEvent(nameChars.Get());