using System; using System.Runtime.InteropServices; using System.Text; // ReSharper disable PrivateFieldCanBeConvertedToLocalVariable namespace PorygonSharp { public abstract class ScriptOptions { private readonly IntPtr _ptr; private delegate void PrintDelegate(string s); private delegate bool ModuleExistsDelegate(IntPtr namePtr, int size); private delegate IntPtr ResolveModuleDelegate(IntPtr namePtr, int size); private readonly PrintDelegate _print; private readonly ModuleExistsDelegate _moduleExists; private readonly ResolveModuleDelegate _resolveModule; protected ScriptOptions() { _ptr = Create(); _print = Print; SetOptionPrintFunc(_ptr, Marshal.GetFunctionPointerForDelegate(_print)); _moduleExists = (namePtr, size) => { var nameArr = new byte[size]; for (var i = 0; i < size; i++) nameArr[i] = Marshal.ReadByte(namePtr, i); var name = Encoding.UTF8.GetString(nameArr); return ModuleExists(name); }; SetOptionModuleExistsFunc(_ptr, Marshal.GetFunctionPointerForDelegate(_moduleExists)); _resolveModule = (namePtr, size) => { var nameArr = new byte[size]; for (var i = 0; i < size; i++) nameArr[i] = Marshal.ReadByte(namePtr, i); var name = Encoding.UTF8.GetString(nameArr); return ResolveModule(name).GetRawPointer(); }; SetOptionResolveModuleFunc(_ptr, Marshal.GetFunctionPointerForDelegate(_resolveModule)); } protected abstract void Print(string s); protected abstract bool ModuleExists(string s); protected abstract Script ResolveModule(string s); internal IntPtr GetRawPointer() { return _ptr; } [DllImport("PorygonLang", EntryPoint = "CreateOptions", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr Create(); [DllImport("PorygonLang", EntryPoint = "SetOptionPrintFunc", CallingConvention = CallingConvention.Cdecl)] private static extern void SetOptionPrintFunc(IntPtr opt, IntPtr func); [DllImport("PorygonLang", EntryPoint = "SetOptionModuleExistsFunc", CallingConvention = CallingConvention.Cdecl)] private static extern void SetOptionModuleExistsFunc(IntPtr opt, IntPtr func); [DllImport("PorygonLang", EntryPoint = "SetOptionResolveModuleFunc", CallingConvention = CallingConvention.Cdecl)] private static extern void SetOptionResolveModuleFunc(IntPtr opt, IntPtr func); } }