/// <summary>Calls method <paramref name="method" /> in SuperMemo</summary> /// <param name="method">The method to call</param> /// <param name="parameters">The method's parameters to pass along with the call</param> /// <returns> /// The returned value (eax register) from the call to <paramref name="method" /> /// </returns> protected int CallNativeMethod(NativeMethod method, dynamic[] parameters) { SMA.Debug($"Executing native method {Enum.GetName(typeof(NativeMethod), method)}."); if (parameters == null) { OnException(new ArgumentNullException(nameof(parameters), $"CallNativeMethod: Called with null 'parameters' for method {method}")); return(-1); } // Possible null reference on parameters var marshalledParameters = new IMarshalledValue[parameters.Length]; for (var i = 0; i < parameters.Length; i++) { var p = parameters[i]; var dynMarshalled = MarshalValue.Marshal(_smProcess, p); if (dynMarshalled is IMarshalledValue marshalled) { marshalledParameters[i] = marshalled; } else { OnException(new ArgumentException($"CallNativeMethod: Parameter n°{i} '{p}' could not be marshalled for method {method}", nameof(p))); return(-1); } } try { switch (method) { case NativeMethod.AppendAndAddElementFromText: var elWdw = marshalledParameters[0].Reference.ToInt32(); var elType = marshalledParameters[1].Reference.ToInt32(); var elDesc = marshalledParameters[2].Reference.ToInt32(); // elWdw.AppendElement(elType, automatic: false); int elemId = Delphi.registerCall3(_callTable[NativeMethod.ElWdw_AppendElement], elWdw, elType, 0); if (elemId <= 0) { return(-1); } // elWdw.AddElementFromText(elDesc); int res = Delphi.registerCall2(_callTable[NativeMethod.ElWdw_AddElementFromText], elWdw, elDesc); return(res > 0 ? elemId : -1); case NativeMethod.PostponeRepetition: elWdw = marshalledParameters[0].Reference.ToInt32(); var interval = marshalledParameters[1].Reference.ToInt32(); // elWdw.ExecuteUncommittedRepetition(inclTopics: true, forceDisplay: false); Delphi.registerCall3(_callTable[NativeMethod.ElWdw_ExecuteUncommittedRepetition], elWdw, 1, 0); // elWdw.ScheduleInInterval(interval); Delphi.registerCall2(_callTable[NativeMethod.ElWdw_ScheduleInInterval], elWdw, interval); // elWdw.SetElementState(DisplayState.Display); //registerCall2(_callTable[NativeMethod.ElWdw_SetElementState], // elWdw, // 2); // elWdw.NextElementInLearningQueue() Delphi.registerCall1(_callTable[NativeMethod.ElWdw_NextElementInLearningQueue], elWdw); return(1); case NativeMethod.ForceRepetitionAndResume: elWdw = marshalledParameters[0].Reference.ToInt32(); interval = marshalledParameters[1].Reference.ToInt32(); var adjustPriority = marshalledParameters[2].Reference.ToInt32(); // elWdw.ForceRepetitionExt(interval, adjustPriority); Delphi.registerCall3(_callTable[NativeMethod.ElWdw_ForceRepetitionExt], elWdw, interval, adjustPriority); // elWdw.NextElementInLearningQueue(); Delphi.registerCall1(_callTable[NativeMethod.ElWdw_NextElementInLearningQueue], elWdw); // elWdw.RestoreLearningMode(); Delphi.registerCall1(_callTable[NativeMethod.ElWdw_RestoreLearningMode], elWdw); return(1); } switch (parameters.Length) { case 1: return(Delphi.registerCall1(_callTable[method], marshalledParameters[0].Reference.ToInt32())); case 2: return(Delphi.registerCall2(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32())); case 3: return(Delphi.registerCall3(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32())); case 4: return(Delphi.registerCall4(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32())); case 5: return(Delphi.registerCall5(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32(), marshalledParameters[4].Reference.ToInt32())); case 6: return(Delphi.registerCall6(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32(), marshalledParameters[4].Reference.ToInt32(), marshalledParameters[5].Reference.ToInt32())); default: throw new NotImplementedException($"No execution path to handle {parameters.Length} parameters."); } } finally { foreach (var param in marshalledParameters) { param.Dispose(); } } }
protected int CallNativeMethod(NativeMethod method, dynamic[] parameters) { var marshalledParameters = parameters.Select(p => MarshalValue.Marshal(_smProcess, p)) .Cast <IMarshalledValue>().ToArray(); try { switch (method) { case NativeMethod.AppendAndAddElementFromText: var elWdw = marshalledParameters[0].Reference.ToInt32(); var elType = marshalledParameters[1].Reference.ToInt32(); var elDesc = marshalledParameters[2].Reference.ToInt32(); // elWdw.AppendElement(elType, automatic: false); int elemId = Delphi.registerCall3(_callTable[NativeMethod.ElWdwAppendElement], elWdw, elType, 0); if (elemId <= 0) { return(-1); } // elWdw.AddElementFromText(elDesc); int res = Delphi.registerCall2(_callTable[NativeMethod.ElWdwAddElementFromText], elWdw, elDesc); return(res > 0 ? elemId : -1); case NativeMethod.PostponeRepetition: elWdw = marshalledParameters[0].Reference.ToInt32(); var interval = marshalledParameters[1].Reference.ToInt32(); // elWdw.ExecuteUncommitedRepetition(inclTopics: true, forceDisplay: false); Delphi.registerCall3(_callTable[NativeMethod.ElWdwExecuteUncommitedRepetition], elWdw, 1, 0); // elWdw.ScheduleInInterval(interval); Delphi.registerCall2(_callTable[NativeMethod.ElWdwScheduleInInterval], elWdw, interval); // elWdw.SetElementState(DisplayState.Display); //registerCall2(_callTable[NativeMethod.ElWdwSetElementState], // elWdw, // 2); // elWdw.NextElementInLearningQueue() Delphi.registerCall1(_callTable[NativeMethod.ElWdwNextElementInLearningQueue], elWdw); return(1); case NativeMethod.ForceRepetitionAndResume: elWdw = marshalledParameters[0].Reference.ToInt32(); interval = marshalledParameters[1].Reference.ToInt32(); var adjustPriority = marshalledParameters[2].Reference.ToInt32(); // elWdw.ForceRepetitionExt(interval, adjustPriority); Delphi.registerCall3(_callTable[NativeMethod.ElWdwForceRepetitionExt], elWdw, interval, adjustPriority); // elWdw.NextElementInLearningQueue(); Delphi.registerCall1(_callTable[NativeMethod.ElWdwNextElementInLearningQueue], elWdw); // elWdw.RestoreLearningMode(); Delphi.registerCall1(_callTable[NativeMethod.ElWdwRestoreLearningMode], elWdw); return(1); } switch (parameters.Length) { case 1: return(Delphi.registerCall1(_callTable[method], marshalledParameters[0].Reference.ToInt32())); case 2: return(Delphi.registerCall2(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32())); case 3: return(Delphi.registerCall3(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32())); case 4: return(Delphi.registerCall4(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32())); case 5: return(Delphi.registerCall5(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32(), marshalledParameters[4].Reference.ToInt32())); case 6: return(Delphi.registerCall6(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32(), marshalledParameters[4].Reference.ToInt32(), marshalledParameters[5].Reference.ToInt32())); default: throw new NotImplementedException($"No execution path to handle {parameters.Length} parameters."); } } finally { foreach (var param in marshalledParameters) { param.Dispose(); } } }