PorygonSharp/PorygonSharp/UserData/UserDataBinaryOperation.cs

51 lines
2.0 KiB
C#

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using PorygonSharp.EvalValues;
using PorygonSharp.Utilities;
namespace PorygonSharp.UserData
{
public class UserDataBinaryOperation
{
private delegate IntPtr BinaryFunctionDelegate(IntPtr objectPtr, IntPtr variable);
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
private readonly BinaryFunctionDelegate _func;
private readonly MethodInfo _info;
private readonly Type _parameterType;
internal IntPtr Handle { get; private set; }
private UserDataBinaryOperation(MethodInfo info)
{
_info = info;
_func = Invoke;
_parameterType = info.GetParameters()[1].ParameterType;
}
public static UserDataBinaryOperation Create(MethodInfo info)
{
var op = new UserDataBinaryOperation(info);
var funcPtr = Marshal.GetFunctionPointerForDelegate(op._func);
var secParType = ScriptType.ScriptTypeHandler.GetScriptType(op._parameterType);
var returnType = ScriptType.ScriptTypeHandler.GetScriptType(op._info.ReturnType);
if (!secParType.HasValue || !returnType.HasValue)
{
return null;
}
op.Handle = CreateUserdataBinaryOperation(funcPtr, secParType.Value, returnType.Value);
return op;
}
private IntPtr Invoke(IntPtr objectPtr, IntPtr variable)
{
var a = GCHandle.FromIntPtr(objectPtr).Target;
var b = new EvalValue(variable);
var bVal = Caster.Cast(b, _parameterType);
var o = _info.Invoke(null, new[] {a, bVal});
return EvalValueCreator.CreateValue(o).GetPointer();
}
[DllImport("PorygonLang", EntryPoint = "CreateUserdataBinaryOperation", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr CreateUserdataBinaryOperation(IntPtr func, IntPtr secondParameterType, IntPtr returnType);
}
}