Пример #1
0
        // Leaves the link in the same state as when it started. The out param leafExprType will be Function if
        // the array is empty in the first bottom-level subarray: {{}, {1,2,3}}.
        internal static int determineIncomingArrayDepth(IMathLink ml /*, out ExpressionType leafExprType*/)
        {
            int       actualDepth = 0;
            ILinkMark mark        = ml.CreateMark();

//        // Initial value just to satisfy compiler; if depth of 0 is returned, then the leafExprType will be ignored by callers.
//        leafExprType = ExpressionType.Function;
            try {
                int    len;
                string head = ml.GetFunction(out len);
                actualDepth = 1;
                while (len > 0)
                {
                    ExpressionType leafExprType = ml.GetNextExpressionType();
                    if (leafExprType == ExpressionType.Function)
                    {
                        head = ml.GetFunction(out len);
                        actualDepth++;
                    }
                    else
                    {
                        break;
                    }
                }
//            // If the last sublist is empty (len == 0), we will walk off the end of the above loop with
//            // leafExprType == ExpressionType.Function, which is what we want.
            } catch (MathLinkException) {
                // Do nothing but clear it. Returning 0 is enough.
                ml.ClearError();
            } finally {
                ml.SeekMark(mark);
                ml.DestroyMark(mark);
            }
            return(actualDepth);
        }
Пример #2
0
        /// <summary>
        /// Reads a Complex number from the link and returns an object of the class set as the
        /// <see cref="IMathLink.ComplexType">ComplexType</see>.
        /// </summary>
        ///
        public object GetComplex(IMathLink ml)
        {
            double re = 0.0;
            double im = 0.0;

            if (ComplexType == null)
            {
                throw new MathLinkException(MathLinkException.MLE_NO_COMPLEX);
            }

            ExpressionType type = ml.GetNextExpressionType();

            switch (type)
            {
            case ExpressionType.Integer:
            case ExpressionType.Real: {
                re = ml.GetDouble();
                break;
            }

            case ExpressionType.Complex: {
                ml.CheckFunctionWithArgCount("Complex", 2);
                re = ml.GetDouble();
                im = ml.GetDouble();
                break;
            }

            default:
                throw new MathLinkException(MathLinkException.MLE_BAD_COMPLEX);
            }
            return(constructComplex(re, im));
        }
Пример #3
0
 // Analogous to the C function of the same name created by mprep for C installable MathLink programs.
 // Note that the built-in DefineExternal function in Mathematica is not abort-safe, so .NET/Link
 // uses its own version, netlinkDefineExternal.
 private static void definePattern(IMathLink ml, string patt, string args, int index)
 {
     ml.PutFunction(KernelLinkImpl.PACKAGE_INTERNAL_CONTEXT + "netlinkDefineExternal", 3);
     ml.Put(patt);
     ml.Put(args);
     ml.Put(index);
 }
Пример #4
0
        // Gives default types to read expressions as. Used when two conditions are met: 1) we have no .NET type info
        // about what we are trying to create, and (2) we have no argType info from M because this is a member of an array
        // (argType tells us merely that it is an array). Will return typeof(Expr) for anything that doesn't map to a .NET type.
        private static Type netTypeFromExpressionType(ExpressionType exprType, IMathLink ml)
        {
            switch (exprType)
            {
            case ExpressionType.Integer:
                return(typeof(int));

            case ExpressionType.Real:
                return(typeof(double));

            case ExpressionType.String:
                return(typeof(string));

            case ExpressionType.Boolean:
                return(typeof(bool));

            case ExpressionType.Symbol:
            case ExpressionType.Function:
                return(typeof(Expr));

            case ExpressionType.Object:
                return(typeof(object));

            case ExpressionType.Complex:
                return(ml.ComplexType != null ? ml.ComplexType : typeof(Expr));

            default:
                // Protection in case we ever add a new value to the enum.
                System.Diagnostics.Debug.Fail("Unhandled ExpressionType enum value in Utils.netTypeFromExpressionType");
                return(null);
            }
        }
Пример #5
0
        public static void WriteEvalToTypesetExpression(IMathLink ml, object obj, int pageWidth, string graphicsFmt, bool useStdForm)
        {
            ml.PutFunction("EvaluatePacket", 1);
            int numArgs = 2 + (useStdForm ? 0 : 1) + (pageWidth > 0 ? 1 : 0);

            ml.PutFunction("EvaluateToTypeset", numArgs);
            ml.Put(obj);
            if (!useStdForm)
            {
                ml.PutSymbol("TraditionalForm");
            }
            if (pageWidth > 0)
            {
                ml.Put(pageWidth);
            }
            ml.Put(graphicsFmt);
            ml.EndPacket();
        }
Пример #6
0
        internal static void discardNext(IKernelLink ml)
        {
            switch (ml.GetNextExpressionType())
            {
            case ExpressionType.Integer:
                ml.GetInteger();
                break;

            case ExpressionType.Real:
                ml.GetDouble();
                break;

            case ExpressionType.Boolean:
            case ExpressionType.Symbol:
                ml.GetSymbol();
                break;

            case ExpressionType.String:
                ml.GetString();
                break;

            case ExpressionType.Object:
                ml.GetObject();
                break;

            // We would get an exception if we called GetComplex() and no complex class was set.
            case ExpressionType.Complex:
            case ExpressionType.Function: {
                IMathLink loop = MathLinkFactory.CreateLoopbackLink();
                try {
                    loop.TransferExpression(ml);
                } finally {
                    loop.Close();
                }
                break;
            }

            default:
                System.Diagnostics.Debug.Fail("Unhandled ExpressionType enum value in Utils.discardNext().");
                break;
            }
        }
Пример #7
0
        public static void WriteEvalToImageExpression(IMathLink ml, object obj, int width, int height, string graphicsFmt, int dpi, bool useFE)
        {
            ml.PutFunction("EvaluatePacket", 1);
            int numArgs = 2 + (useFE ? 1 : 0) + (dpi > 0 ? 1 : 0) + (width > 0 || height > 0 ? 1 : 0);

            ml.PutFunction("EvaluateToImage", numArgs);
            ml.Put(obj);
            if (useFE)
            {
                ml.Put(true);
            }
            ml.Put(graphicsFmt);
            if (dpi > 0)
            {
                ml.PutFunction("Rule", 2);
                ml.PutSymbol("ImageResolution");
                ml.Put(dpi);
            }
            if (width > 0 || height > 0)
            {
                ml.PutFunction("Rule", 2);
                ml.PutSymbol("ImageSize");
                ml.PutFunction("List", 2);
                if (width > 0)
                {
                    ml.Put(width);
                }
                else
                {
                    ml.PutSymbol("Automatic");
                }
                if (height > 0)
                {
                    ml.Put(height);
                }
                else
                {
                    ml.PutSymbol("Automatic");
                }
            }
            ml.EndPacket();
        }
Пример #8
0
        /// <summary>
        /// Writes an instance of the class specified as the <see cref="IMathLink.ComplexType">ComplexType</see> on the link.
        /// </summary>
        ///
        public void PutComplex(IMathLink ml, object obj)
        {
            if (ComplexType == null)
            {
                throw new MathLinkException(MathLinkException.MLE_NO_COMPLEX);
            }

            double re = 0;
            double im = 0;

            try {
                re = getRealPart(obj);
                im = getImaginaryPart(obj);
            } catch (Exception e) {
                // Shouldn't get here.
                ml.PutSymbol("$Failed");
                throw e;
            }
            ml.PutFunction("Complex", 2);
            // Use Put(double), because it has code to handle NaN, infinity.
            ml.Put(re);
            ml.Put(im);
        }
Пример #9
0
        // These next methods are called by implementors of the KernelLink "evaluateTo" methods. It is useful to separate the
        // code to create the appropriate expression to send (which is what these methods do) and the code that runs the
        // reading loop. In these methods, obj must be a string or Expr.

        // This is ready to accommodate an evaluateToMathML() function, but I have not added such a function to KernelLink yet.
        public static void WriteEvalToStringExpression(IMathLink ml, Object obj, int pageWidth, string format)
        {
            ml.PutFunction("EvaluatePacket", 1);
            ml.PutFunction("ToString", 3);
            if (obj is string)
            {
                ml.PutFunction("ToExpression", 1);
            }
            ml.Put(obj);
            ml.PutFunction("Rule", 2);
            ml.PutSymbol("FormatType");
            ml.PutSymbol(format);
            ml.PutFunction("Rule", 2);
            ml.PutSymbol("PageWidth");
            if (pageWidth > 0)
            {
                ml.Put(pageWidth);
            }
            else
            {
                ml.PutSymbol("Infinity");
            }
            ml.EndPacket();
        }
Пример #10
0
 public override void TransferExpression(IMathLink source)
 {
     impl.TransferExpression(source);
 }
Пример #11
0
 public static Expr CreateFromLink(IMathLink ml)
 {
     return(new Expr(Wolfram.NETLink.Expr.CreateFromLink(ml)));
 }
Пример #12
0
 public void Put(IMathLink ml)
 {
     expr.Put(ml);
 }
Пример #13
0
 public abstract void TransferExpression(IMathLink source);
Пример #14
0
 public static Wolfram.NETLink.IKernelLink   CreateKernelLink(IMathLink ml)
 {
     RegisterMathLinkFactory(); return(Wolfram.NETLink.MathLinkFactory.CreateKernelLink(ml));
 }
Пример #15
0
        /// <summary>
        /// Analogous to the MLInstall function in mprep-generated C programs.
        /// </summary>
        /// <param name="ml"></param>
        /// <returns>Whether it succeeded or not.</returns>
        ///
        public static bool install(IMathLink ml)
        {
            // Adding nXX functions here requires also adding the symbols to the NETLink`NET.m file.
            try {
                ml.Connect();
                ml.Put("Begin[\"" + KernelLinkImpl.PACKAGE_INTERNAL_CONTEXT + "\"]");
                definePattern(ml, "nCall[typeName_String, obj_Symbol, callType_Integer, isByVal_, memberName_String, argCount_Integer, typesAndArgs___]", "{typeName, obj, callType, isByVal, memberName, argCount, typesAndArgs}", CALL);
                definePattern(ml, "nLoadType1[type_String, assemblyName_]", "{type, assemblyName}", LOADTYPE1);
                definePattern(ml, "nLoadType2[type_String, assemblyObj_]", "{type, assemblyObj}", LOADTYPE2);
                definePattern(ml, "nLoadExistingType[typeObject_?NETObjectQ]", "{typeObject}", LOADEXISTINGTYPE);
                definePattern(ml, "nLoadAssembly[assemblyNameOrPath_String, suppressErrors_]", "{assemblyNameOrPath, suppressErrors}", LOADASSEMBLY);
                definePattern(ml, "nLoadAssemblyFromDir[assemblyName_String, dir_String]", "{assemblyName, dir}", LOADASSEMBLYFROMDIR);
                definePattern(ml, "nGetAssemblyObject[asmName_String]", "{asmName}", GETASSEMBLYOBJ);
                definePattern(ml, "nGetTypeObject[aqTypeName_String]", "{aqTypeName}", GETTYPEOBJ);
                definePattern(ml, "nReleaseObject[instances:{__Symbol}]", "{instances}", RELEASEOBJECT);
                definePattern(ml, "nMakeObject[typeName_String, argType_Integer, val_]", "{typeName, argType, val}", MAKEOBJECT);
                definePattern(ml, "nVal[obj_?NETObjectQ]", "{obj}", VAL);
                definePattern(ml, "nReflectType[typeName_String]", "{typeName}", REFLECTTYPE);
                definePattern(ml, "nReflectAsm[asmName_String]", "{asmName}", REFLECTASM);
                definePattern(ml, "nSetComplex[typeName_String]", "{typeName}", SETCOMPLEX);
                definePattern(ml, "nSameQ[obj1_?NETObjectQ, obj2_?NETObjectQ]", "{obj1, obj2}", SAMEQ);
                definePattern(ml, "nInstanceOf[obj_?NETObjectQ, aqTypeName_String]", "{obj, aqTypeName}", INSTANCEOF);
                definePattern(ml, "nCast[obj_?NETObjectQ, aqTypeName_String]", "{obj, aqTypeName}", CAST);
                definePattern(ml, "nPeekTypes[]", "{}", PEEKTYPES);
                definePattern(ml, "nPeekObjects[]", "{}", PEEKOBJECTS);
                definePattern(ml, "nPeekAssemblies[]", "{}", PEEKASSEMBLIES);

                definePattern(ml, "nCreateDelegate[typeName_String, mFunc_String, sendTheseArgs_Integer, callsUnshare:(True | False), wrapInNETBlock:(True | False)]", "{typeName, mFunc, sendTheseArgs, callsUnshare, wrapInNETBlock}", CREATEDELEGATE);
                definePattern(ml, "nDefineDelegate[name_String, retTypeName_String, paramTypeNames_List]", "{name, retTypeName, paramTypeNames}", DEFINEDELEGATE);
                definePattern(ml, "nDlgTypeName[eventObject_?NETObjectQ, aqTypeName_String, evtName_String]", "{eventObject, aqTypeName, evtName}", DLGTYPENAME);
                definePattern(ml, "nAddHandler[eventObject_?NETObjectQ, aqTypeName_String, evtName_String, delegate_?NETObjectQ]", "{eventObject, aqTypeName, evtName, delegate}", ADDHANDLER);
                definePattern(ml, "nRemoveHandler[eventObject_?NETObjectQ, aqTypeName_String, evtName_String, delegate_?NETObjectQ]", "{eventObject, aqTypeName, evtName, delegate}", REMOVEHANDLER);

                definePattern(ml, "nCreateDLL1[funcName_String, dllName_String, callConv_String, retTypeName_String, argTypeNames_, areOutParams_, strFormat_String]", "{funcName, dllName, callConv, retTypeName, argTypeNames, areOutParams, strFormat}", CREATEDLL1);
                definePattern(ml, "nCreateDLL2[decl_String, refAsms_, lang_String]", "{decl, refAsms, lang}", CREATEDLL2);

                definePattern(ml, "nModal[modal:(True | False), formToActivate_?NETObjectQ]", "{modal, formToActivate}", MODAL);
                definePattern(ml, "nShow[formToActivate_?NETObjectQ]", "{formToActivate}", SHOW);
                definePattern(ml, "nShareKernel[sharing:(True | False)]", "{sharing}", SHAREKERNEL);
                definePattern(ml, "nAllowUIComputations[allow:(True | False)]", "{allow}", ALLOWUICOMPS);
                definePattern(ml, "nUILink[name_String, prot_String]", "{name, prot}", UILINK);

                definePattern(ml, "nIsCOMProp[obj_?NETObjectQ, memberName_String]", "{obj, memberName}", ISCOMPROP);
                definePattern(ml, "nCreateCOM[clsIDOrProgID_String]", "{clsIDOrProgID}", CREATECOM);
                definePattern(ml, "nGetActiveCOM[clsIDOrProgID_String]", "{clsIDOrProgID}", GETACTIVECOM);
                definePattern(ml, "nReleaseCOM[obj_?NETObjectQ]", "{obj}", RELEASECOM);
                definePattern(ml, "nLoadTypeLibrary[tlbPath_String, safeArrayAsArray_, assemblyFile_String]", "{tlbPath, safeArrayAsArray, assemblyFile}", LOADTYPELIBRARY);

                definePattern(ml, "nGetException[]", "{}", GETEXCEPTION);

                definePattern(ml, "nConnectToFEServer[linkName_String]", "{linkName}", CONNECTTOFE);
                definePattern(ml, "nDisconnectToFEServer[]", "{}", DISCONNECTTOFE);

                // For speed testing:
                definePattern(ml, "noop[]", "{}", NOOP);
                definePattern(ml, "noop2[argc_Integer, args___]", "{argc, args}", NOOP2);

                // Here we define the argTypeToInteger function by sending
                // MapThread[(argTypeToInteger[#1] = #2)&, {ToExpression /@ argTypePatterns, {... ARGTYPE_ constants ...}}]
                ml.PutFunction("MapThread", 2);
                ml.PutFunction("Function", 1);
                ml.PutFunction("Set", 2);
                ml.PutFunction("argTypeToInteger", 1);
                ml.PutFunction("Slot", 1);
                ml.Put(1);
                ml.PutFunction("Slot", 1);
                ml.Put(2);
                ml.PutFunction("List", 2);
                ml.PutFunction("Map", 2);
                ml.PutSymbol("ToExpression");
                ml.Put(argTypePatterns);
                ml.PutFunction("List", 13);
                ml.Put(ARGTYPE_INTEGER);
                ml.Put(ARGTYPE_REAL);
                ml.Put(ARGTYPE_STRING);
                ml.Put(ARGTYPE_BOOLEAN);
                ml.Put(ARGTYPE_NULL);
                ml.Put(ARGTYPE_MISSING);
                ml.Put(ARGTYPE_OBJECTREF);
                ml.Put(ARGTYPE_VECTOR);
                ml.Put(ARGTYPE_MATRIX);
                ml.Put(ARGTYPE_TENSOR3);
                ml.Put(ARGTYPE_LIST);
                ml.Put(ARGTYPE_COMPLEX);
                ml.Put(ARGTYPE_OTHER);

                ml.Put("End[]");
                ml.PutSymbol("End");
                ml.Flush();

                return(true);
            } catch (MathLinkException) {
                return(false);
            }
        }
Пример #16
0
 /// <summary>
 /// Creates an IKernelLink from an <see cref="IMathLink"/>.
 /// </summary>
 /// <remarks>
 /// You can think of IKernelLink as a "decorator" for IMathLink. It builds on top of IMathLink by providing
 /// extra capabilities. If you have an IMathLink object, you can use this method to construct an
 /// IKernelLink implementation out of it.
 /// <para>
 /// Very few programmers will ever use this method. It is intended mainly for developers who are creating their
 /// own IKernelLink implementations. They only need to write the functionality of an IMathLink, and then they
 /// can use this method to get the extra features of an IKernelLink for free.
 /// </para>
 /// </remarks>
 /// <param name="ml">The IMathLink to "wrap".</param>
 /// <returns>The created link.</returns>
 /// <exception cref="MathLinkException">If the opening of the link fails.</exception>
 ///
 public static IKernelLink CreateKernelLink(IMathLink ml)
 {
     return(new WrappedKernelLink(ml));
 }
Пример #17
0
 internal NativeMark(IMathLink ml, IntPtr mark)
 {
     this.mark = mark;
     this.ml   = ml;
 }
Пример #18
0
 public WrappedKernelLink(IMathLink ml)
 {
     SetMathLink(ml);
     MessageArrived += new MessageHandler(interruptDetector);
 }
Пример #19
0
        // Can read any kind of array, except for jagged arrays that are multidimensional at the beginning, like [][,]
        // (jagged at start like [,][] or [,...][][] is OK, but only if we know the type, not for an Array slot). Recall
        // that mixed array types are read backwards, so [][,] is a 2-deep array of element type [] (i.e., it is multidimensional
        // at the start, not the end). One more limitation: For an Array argument slot, if the incoming array is 3-deep or deeper,
        // it must be rectangular, not jagged.
        // We know the incoming expression has head List.
        internal static Array readArbitraryArray(IMathLink ml, Type t)
        {
            int len;

            if (t == typeof(Array))
            {
                ExpressionType leafExprType;
                Type           leafType;
                // For the Array type, we have no clue about how the leaf elements will be read. Thus we need to peek into
                // the incoming data to decide what type it is.
                int           depth = determineIncomingArrayDepth(ml);
                ILinkMark     mark  = ml.CreateMark();
                ILoopbackLink loop  = null;
                try {
                    if (depth == 1)
                    {
                        len = ml.CheckFunction("List");
                        if (len == 0)
                        {
                            throw new MathLinkException(MathLinkException.MLE_EMPTY_ARRAY);
                        }
                        leafExprType = ml.GetNextExpressionType();
                        ml.SeekMark(mark);
                        leafType = netTypeFromExpressionType(leafExprType, ml);
                        // Fail if data could only be read as Expr. This means that we cannot pass a list of arbitrary expressions
                        // to an arg slot typed as Array. It would have to be typed as Expr[]. We make this choice to provide
                        // more meaningful error reporting for the cases where the array has bogus data in it. We assume that
                        // this convenience outweighs the very rare cases where a programmer would want to pass an array of exprs
                        // for an Array slot (they could always create the array separately and pass it as an object reference).
                        if (leafType == typeof(Expr))
                        {
                            if (leafExprType == ExpressionType.Complex)
                            {
                                throw new MathLinkException(MathLinkException.MLE_NO_COMPLEX);
                            }
                            else
                            {
                                throw new MathLinkException(MathLinkException.MLE_BAD_ARRAY);
                            }
                        }
                        return((Array)ml.GetArray(leafType, 1));
                    }
                    else if (depth == 2)
                    {
                        // The loopback link is just a utility for quickly reading expressions off the link (via TransferExpression).
                        // Nothing is ever read back off the loopback link.
                        loop = MathLinkFactory.CreateLoopbackLink();
                        // Determine if the array is rectangular or jagged.
                        len = ml.CheckFunction("List");
                        bool isJagged      = false;
                        bool foundLeafType = false;
                        // This next assignment is strictly for the compiler. The value will never be used
                        // unless it is set to an actual value below. We have an existing function that will get
                        // the leafExprType of the incoming array (getLeafExprType()), but we also need to check if the array
                        // is jagged here, so we will do both tasks at once and save a little time.
                        leafExprType = ExpressionType.Integer;
                        int lenAtLevel2 = ml.CheckFunction("List");
                        if (lenAtLevel2 > 0)
                        {
                            leafExprType  = ml.GetNextExpressionType();
                            foundLeafType = true;
                        }
                        // peel off all the elements in the first sublist.
                        for (int j = 0; j < lenAtLevel2; j++)
                        {
                            loop.TransferExpression(ml);
                        }
                        // For each remaining sublist, check its length and peel off its members. At this point, though, we
                        // cannot be guaranteed that all elements are lists (or, at least, guaranteed that it is an error
                        // if they are not). They could be Null if the array is jagged: {{1, 2}, Null}.
                        for (int i = 1; i < len; i++)
                        {
                            ExpressionType nextExprType = ml.GetNextExpressionType();
                            if (nextExprType == ExpressionType.Object)
                            {
                                isJagged = true;
                                // OK to have null as an element in a jagged array.
                                if (ml.GetObject() != null)
                                {
                                    throw new MathLinkException(MathLinkException.MLE_BAD_ARRAY_SHAPE);
                                }
                            }
                            else if (nextExprType == ExpressionType.Function)
                            {
                                int thisLength = ml.CheckFunction("List");
                                if (!foundLeafType && thisLength > 0)
                                {
                                    leafExprType  = ml.GetNextExpressionType();
                                    foundLeafType = true;
                                }
                                if (thisLength != lenAtLevel2)
                                {
                                    isJagged = true;
                                    break;
                                }
                                else
                                {
                                    for (int j = 0; j < thisLength; j++)
                                    {
                                        loop.TransferExpression(ml);
                                    }
                                }
                            }
                            else
                            {
                                throw new MathLinkException(MathLinkException.MLE_BAD_ARRAY_DEPTH);
                            }
                        }
                        // If the array is empty we cannot create a .NET array for it, as there is no type info for the array we are creating.
                        if (!foundLeafType)
                        {
                            throw new MathLinkException(MathLinkException.MLE_EMPTY_ARRAY);
                        }
                        leafType = netTypeFromExpressionType(leafExprType, ml);
                        ml.SeekMark(mark);
                        if (isJagged)
                        {
                            ml.CheckFunction("List");
                            Array result = Array.CreateInstance(Array.CreateInstance(leafType, 0).GetType(), len);
                            for (int i = 0; i < len; i++)
                            {
                                // Have to check if elements are lists or Null.
                                ExpressionType nextExprType = ml.GetNextExpressionType();
                                if (nextExprType == ExpressionType.Function)
                                {
                                    result.SetValue(ml.GetArray(leafType, 1), i);
                                }
                                else
                                {
                                    string sym = ml.GetSymbol();
                                    if (sym != "Null")
                                    {
                                        throw new MathLinkException(MathLinkException.MLE_BAD_ARRAY_SHAPE);
                                    }
                                    result.SetValue(null, i);
                                }
                            }
                            return(result);
                        }
                        else
                        {
                            return(ml.GetArray(leafType, 2));
                        }
                    }
                    else
                    {
                        // For an Array argument slot, we only support passing >2-deep rectangular arrays, not jagged.
                        for (int i = 0; i < depth; i++)
                        {
                            ml.CheckFunction("List");
                        }
                        leafExprType = ml.GetNextExpressionType();
                        leafType     = netTypeFromExpressionType(leafExprType, ml);
                        ml.SeekMark(mark);
                        return(ml.GetArray(leafType, depth));
                    }
                } finally {
                    if (loop != null)
                    {
                        loop.Close();
                    }
                    ml.DestroyMark(mark);
                }
            }
            else
            {
                // We have the actual array shape encoded in the type. Either [], [,..], or array-of-arrays: [][]....
                int  arrayRank   = t.GetArrayRank();
                Type elementType = t.GetElementType();
                if (elementType.IsArray)
                {
                    if (arrayRank > 1)
                    {
                        // Don't support multidimensional array at start of jagged array: [][,]. Recall that mixed array types
                        // are read backwards, so [][,] is a 2-deep array of element type [].
                        throw new MathLinkException(MathLinkException.MLE_MULTIDIM_ARRAY_OF_ARRAY);
                    }
                    len = ml.CheckFunction("List");
                    Array result = Array.CreateInstance(elementType, len);
                    for (int i = 0; i < len; i++)
                    {
                        ExpressionType nextExprType = ml.GetNextExpressionType();
                        if (nextExprType == ExpressionType.Function)
                        {
                            result.SetValue(readArbitraryArray(ml, elementType), i);
                        }
                        else
                        {
                            string sym = ml.GetSymbol();
                            if (sym != "Null")
                            {
                                throw new MathLinkException(MathLinkException.MLE_BAD_ARRAY_SHAPE);
                            }
                            result.SetValue(null, i);
                        }
                    }
                    return(result);
                }
                else if (elementType == typeof(Array))
                {
                    // Don't support Array[].
                    throw new MathLinkException(MathLinkException.MLE_ARRAY_OF_ARRAYCLASS);
                }
                else
                {
                    return(ml.GetArray(elementType, arrayRank));
                }
            }
        }
Пример #20
0
 public void SetMathLink(IMathLink ml)
 {
     impl = ml;
 }
Пример #21
0
        public virtual void HandlePacket(PacketType pkt)
        {
            switch (pkt)
            {
            // If you ever change the default behavior on the 4 "answer" packets to read off the link,
            // you'll need to add a seekMark in NativeKernelLink.waitForAnswer...
            case PacketType.Return:
            case PacketType.InputName:
            case PacketType.ReturnText:
            case PacketType.ReturnExpression:
            case PacketType.Menu:
            case PacketType.Message:
                break;

            // From here on, the cases do actual work.
            case PacketType.Call: {
                ExpressionType type = GetExpressionType();
                if (type == ExpressionType.Integer)
                {
                    // A normal CallPacket representing a call to .NET via nCall.
                    callPktHandler.handleCallPacket(this);
                }
                else
                {
                    // A CallPacket destined for the FE via MathLink`CallFrontEnd[] and routed through
                    // .NET due to ShareFrontEnd[]. This would only be in a 5.1 FE, as earlier
                    // versions do not use CallPacket and later versions would use the FE's Service Link.
                    IMathLink feServerLink = callPktHandler.FEServerLink;
                    if (feServerLink != null)
                    {
                        feServerLink.PutFunction("CallPacket", 1);
                        feServerLink.TransferExpression(this);
                        // FE will always reply to a CallPacket. Note that it is technically possible for
                        // the FE to send back an EvaluatePacket, which means that we really need to run a
                        // little loop here, not just write the result back to the kernel. But this branch
                        // is only for a 5.1 FE, and I don't think that the 5.1 FE ever does that.
                        TransferExpression(feServerLink);
                    }
                }
                break;
            }

            case PacketType.Display:
            case PacketType.DisplayEnd: {
                IMathLink feServerLink = callPktHandler.FEServerLink;
                if (feServerLink != null)
                {
                    if (accumulatingPS == null)
                    {
                        accumulatingPS = new System.Text.StringBuilder(34000);  // 34K is large enough to hold an entire packet
                    }
                    accumulatingPS.Append(GetString());
                    if (pkt == PacketType.DisplayEnd)
                    {
                        // XXXPacket[stuff] ---> Cell[GraphicsData["PostScript", stuff], "Graphics"]
                        feServerLink.PutFunction("FrontEnd`FrontEndExecute", 1);
                        feServerLink.PutFunction("FrontEnd`NotebookWrite", 2);
                        feServerLink.PutFunction("FrontEnd`SelectedNotebook", 0);
                        feServerLink.PutFunction("Cell", 2);
                        feServerLink.PutFunction("GraphicsData", 2);
                        feServerLink.Put("PostScript");
                        feServerLink.Put(accumulatingPS.ToString());
                        feServerLink.Put("Graphics");
                        feServerLink.Flush();
                        accumulatingPS = null;
                    }
                }
                else
                {
                    Debug.WriteLine("Got PacketType.Display in handlePacket, but no FE link");
                }
                break;
            }

            case PacketType.Input:
            case PacketType.InputString: {
                IMathLink feServerLink = callPktHandler.FEServerLink;
                if (feServerLink != null)
                {
                    feServerLink.PutFunction(pkt == PacketType.InputString ? "InputStringPacket" : "InputPacket", 1);
                    feServerLink.Put(GetString());
                    feServerLink.Flush();
                    NewPacket();
                    Put(feServerLink.GetString());
                    Flush();
                }
                break;
            }

            case PacketType.Text:
            case PacketType.Expression: {
                // Print output, or message text.
                IMathLink feServerLink = callPktHandler.FEServerLink;
                if (feServerLink != null)
                {
                    // XXXPacket[stuff] ---> Cell[stuff, "Print"]
                    feServerLink.PutFunction("FrontEnd`FrontEndExecute", 1);
                    feServerLink.PutFunction("FrontEnd`NotebookWrite", 2);
                    feServerLink.PutFunction("FrontEnd`SelectedNotebook", 0);
                    feServerLink.PutFunction("Cell", 2);
                    feServerLink.TransferExpression(this);
                    feServerLink.Put((lastPktWasMsg) ? "Message" : "Print");
                    feServerLink.Flush();
                }
                else
                {
                    // For one type of PacketType.Expression, no part of it has been read yet. Thus we must "open" the
                    // packet so that later calls to newPacket() throw it away.
                    if (pkt == PacketType.Expression)
                    {
                        int ignore;
                        GetFunction(out ignore);
                    }
                }
                break;
            }

            case PacketType.FrontEnd: {
                // This case is different from the others. At the point of entry, the link is at the point
                // _before_ the "packet" has been read. As a result, we must at least open the packet.
                // Note that PacketType.FrontEnd is really just a fall-through for unrecognized packets. We don't have any
                // checks that it is truly intended for the FE.
                IMathLink feServerLink = callPktHandler.FEServerLink;
                if (feServerLink != null)
                {
                    ILinkMark mark = CreateMark();
                    try {
                        // Wrap FrontEndExecute around it if not already there.
                        int    ignore;
                        string wrapper = GetFunction(out ignore);
                        if (wrapper != "FrontEnd`FrontEndExecute")
                        {
                            feServerLink.PutFunction("FrontEnd`FrontEndExecute", 1);
                        }
                    } finally {
                        SeekMark(mark);
                        DestroyMark(mark);
                    }
                    feServerLink.TransferExpression(this);
                    feServerLink.Flush();
                    // Wait until either the fe is ready (because what we just sent causes a return value)
                    // or kernel is ready (the computation is continuing because the kernel is not waiting
                    // for a return value).
                    do
                    {
                        System.Threading.Thread.Sleep(50);
                    } while (!feServerLink.Ready && !Ready);
                    if (feServerLink.Ready)
                    {
                        // fe link has something to return to kernel from last PacketType.FrontEnd we sent it.
                        TransferExpression(feServerLink);
                        Flush();
                    }
                }
                else
                {
                    // It's OK to get here. For example, this happens if you don't share the fe, but have a
                    // button that calls NotebookCreate[]. This isn't a very good example, because that
                    // function expects the fe to return something, so Java will hang. you will get into
                    // trouble if you make calls on the fe that expect a return. Everything is OK for calls
                    // that don't expect a return, though.
                    int ignore;
                    GetFunction(out ignore); // Must at least open the packet, so newPacket (back in caller) will get rid of it.
                }
                break;
            }

            default:
                break;
            }
            lastPktWasMsg = pkt == PacketType.Message;
        }