Example #1
0
        /// <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();
                }
            }
        }
Example #2
0
        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();
                }
            }
        }