PorygonSharp/PorygonSharp/EvalValues/DelegateEvalValue.cs

47 lines
1.6 KiB
C#

using System;
using System.Linq;
using System.Runtime.InteropServices;
using PorygonSharp.UserData;
using PorygonSharp.Utilities;
namespace PorygonSharp.EvalValues
{
public class DelegateEvalValue : EvalValue
{
private delegate IntPtr InvokeDelegate(IntPtr _, IntPtr options,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]IntPtr[] parameters, int parameterCount);
private readonly Delegate _delegate;
private readonly InvokeDelegate _handler;
private readonly IntPtr _funcPtr;
public DelegateEvalValue(Delegate del)
{
_delegate = del;
_handler = Invoke;
_funcPtr = Marshal.GetFunctionPointerForDelegate(_handler);
Handle = EvalValueCreator.CreateFunctionEvalValue(_funcPtr, IntPtr.Zero);
}
private IntPtr Invoke(IntPtr _, IntPtr options, IntPtr[] parPtrs, int parameterCount)
{
var parameters = new object[parameterCount];
var parametersTypes = _delegate.Method.GetParameters().Select(x => x.ParameterType).ToArray();
for (var i = 0; i < parameterCount; i++)
{
var val = new EvalValue(parPtrs[i]);
parameters[i] = Caster.Cast(val, parametersTypes[i]);
}
try
{
var result = _delegate.DynamicInvoke(parameters);
return new UserDataReturnValue(EvalValueCreator.CreateValue(result)).GetPointer();
}
catch (Exception e)
{
return new UserDataReturnValue(e.ToString()).GetPointer();
}
}
}
}