using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using PorygonSharp.EvalValues; using PorygonSharp.Utilities; namespace PorygonSharp.UserData { internal class UserDataFunctionField : UserDataField { public readonly IntPtr MethodPtr; private readonly List _callers; public UserDataFunctionField(MethodInfo method, IntPtr methodPtr) { _getter = ptr => { var funcPtr = Marshal.GetFunctionPointerForDelegate(_callers[0]); var val = EvalValueCreator.FunctionEvalValue(funcPtr, ptr); for (var i = 1; i < _callers.Count; i++) { funcPtr = Marshal.GetFunctionPointerForDelegate(_callers[i]); RegisterFunctionEvalValueOption(val.GetPointer(), funcPtr, ptr); } return val.GetPointer(); }; MethodPtr = methodPtr; _callers = new List(){CreateCaller(method)}; } private CallerDelegate CreateCaller(MethodInfo method) { var parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray(); return (parent, scriptOptions, parameters, size) => { var evaluatedParameters = new object[size]; for (var i = 0; i < size; i++) { var eval = new EvalValue(parameters[i]); evaluatedParameters[i] = Caster.Cast(eval, parameterTypes[i]); } var parentObj = GCHandle.FromIntPtr(parent).Target; var result = method.Invoke(parentObj, evaluatedParameters); return EvalValueCreator.CreateValue(result).GetPointer(); }; } internal void RegisterOption(MethodInfo method) { _callers.Add(CreateCaller(method)); } [DllImport("PorygonLang", EntryPoint = "RegisterFunctionEvalValueOption",CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr RegisterFunctionEvalValueOption(IntPtr val, IntPtr func, IntPtr obj); } }