(***********************************************************************
Mathematica-Compatible Notebook
This notebook can be used on any computer system with Mathematica 3.0,
MathReader 3.0, or any compatible application. The data for the notebook
starts with the line of stars above.
To get the notebook into a Mathematica-compatible application, do one of
the following:
* Save the data starting with the line of stars above into a file
with a name ending in .nb, then open the file inside the application;
* Copy the data starting with the line of stars above to the
clipboard, then use the Paste menu command inside the application.
Data for notebooks contains only printable 7-bit ASCII and can be
sent directly in email or through ftp in text mode. Newlines can be
CR, LF or CRLF (Unix, Macintosh or MS-DOS style).
NOTE: If you modify the data for this notebook not in a Mathematica-
compatible application, you must delete the line below containing the
word CacheID, otherwise Mathematica-compatible applications may try to
use invalid cache data.
For more information on notebooks and Mathematica-compatible
applications, contact Wolfram Research:
web: http://www.wolfram.com
email: info@wolfram.com
phone: +1-217-398-0700 (U.S.)
Notebook reader applications are available free of charge from
Wolfram Research.
***********************************************************************)
(*CacheID: 232*)
(*NotebookFileLineBreakTest
NotebookFileLineBreakTest*)
(*NotebookOptionsPosition[ 314312, 10471]*)
(*NotebookOutlinePosition[ 315367, 10507]*)
(* CellTagsIndexPosition[ 315323, 10503]*)
(*WindowFrame->Normal*)
Notebook[{
Cell[CellGroupData[{Cell[TextData[{
StyleBox["A ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" Tutorial\n\n",
Evaluatable->False,
AspectRatioFixed->True]
}], "Title",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["Todd Gayley\nWolfram Research\n"], "Subtitle",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" is a library of functions that implement a protocol for sending and \
receiving ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" expressions. Its uses fall into two general categories. The easiest and \
most common application is to allow external functions written in other \
languages to be called from within the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" environment. If you have an algorithm that needs to be implemented in a \
compiled language for efficiency reasons, or if you have code that you don't \
want to rewrite in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", it is a relatively simple matter to incorporate the routines into ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". This use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" is treated in the first chapter of this tutorial.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The second use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" is to allow your program, running in the foreground, to use the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" kernel in the background as a computational engine. In effect, the \
program is a \"front end\" for the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" kernel. This requires a deeper understanding of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", and is treated in the second chapter.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Each of these two chapters is designed to stand on its own, so there is \
some repetition. There are also topics that are relevant to all ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" programmers that are treated more fully in one chapter than in the other. \
I strongly recommend that you read both, but keep in mind that some of the \
information may not apply to you, depending on how you plan to use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["This document is designed to supplement the information in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink Reference Guide",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", which is the main documentation for ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". There is also some information on newer features of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Major New Feautres of Mathematica Version 2.2",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" document, which comes with Version 2.2, and is also available on \
MathSource. My intention here is to flesh out some details, provide useful \
code fragments, discuss some underdocumented features, and show how to \
accomplish some common tasks.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The information presented here refers to Version 2.2.2 of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" and later. Most of the information is also correct for earlier versions, \
but a few of the functions and features may not be present.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"1. Calling External Programs from the Mathematica Kernel"], "Special3",
Evaluatable->False,
PageBreakAbove->True,
AspectRatioFixed->True],
Cell[TextData["1.1 The Simplest Example: addtwo"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"1.2 Using :Evaluate: to Include Accessory Mathematica Code"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["1.3 Putting and Getting Arguments Manually"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["1.4 Passing Lists and Arrays"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["1.5 Passing Arbitrary Expressions"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["1.6 Requesting Evaluations by the Kernel"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["1.7 Error Handling"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["1.8 Troubleshooting and Debugging"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["1.9 Large Projects"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["1.10 Special Topics"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"2. Calling the Mathematica Kernel from External Programs"], "Special3",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["2.1 A Simple Program"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["2.2 Opening a Link to the Kernel"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["2.3 Sending Expressions to the Kernel"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["2.4 Receiving Expressions from the Kernel"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["2.5 Blocking, Yield Functions, and All That"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["2.6 Graphics"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["3. Using Other Languages"], "Special3",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["3.1 C++"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["3.2 FORTRAN and Others"], "Special4",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData[{
StyleBox["1. Calling External Programs from the ",
Evaluatable->False,
PageBreakAbove->True,
AspectRatioFixed->True,
FontSlant->"Plain"],
StyleBox["Mathematica",
Evaluatable->False,
PageBreakAbove->True,
AspectRatioFixed->True],
StyleBox[" Kernel",
Evaluatable->False,
PageBreakAbove->True,
AspectRatioFixed->True,
FontSlant->"Plain"]
}], "Subsubtitle",
Evaluatable->False,
PageBreakAbove->True,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["I will refer to external functions that are called from ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" as \"installable\" functions, since they use the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" mechanism to be incorporated into the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" environment. The intent is that you should be able to take pre-existing C \
language routines, and with as little effort as possible (ideally with no \
source code changes to the routines themselves), package them so they can be \
called from ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". For each function you want to call from ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", you write a template entry that specifies the name of the function, the \
arguments that the function needs to be passed and their types, and the type \
of argument it returns. This template file is then passed through a tool \
called mprep, which writes C code that manages most, possibly all, of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox["-related aspects of the program. ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"I want to emphasize how easy, even trivial, it is to perform these steps \
for many external functions. With just a little more effort you can handle \
unusual functions or more sophisticated communication. The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink Reference Guide",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" is perhaps a little intimidating, but some of the information is not \
directly relevant for programmers who merely want to call external functions \
from ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". I hope that this chapter will encapsulate much of the information you \
need in a concise form.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["1.1 The Simplest Example: addtwo"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Let's look at a trivial example of an installable program, the addtwo \
program that is supplied with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". We will modify the program in several ways to demonstrate more advanced \
techniques. Here is the C source file addtwo.c:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" #include \"mathlink.h\"\n\n int addtwo(int i, int j) {\n \
return i+j;\n }\n\n int main(int argc, char* argv[]) {\n \
return MLMain(argc, argv);\n }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Note that if you already had a C routine that took two ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["int",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["s and returned an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["int",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", all you would have to do to make it installable would be to insert the \
one-line ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["main",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function (actually, for Windows users ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["main",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" is slightly more complicated, but it is still something that can simply \
be pasted into your own code). The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["main",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" function is simply a \"stub\" that calls the real main function (named ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLMain",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["), which is written by mprep.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["Here is the template file addtwo.tm:"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :Begin:\n :Function: addtwo\n :Pattern: \
AddTwo[i_Integer, j_Integer]\n :Arguments: { i, j }\n \
:ArgumentTypes: { Integer, Integer }\n :ReturnType: Integer\n \
:End:"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Function:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line specifies the name of the C routine. The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Pattern:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line shows how the routine will be called in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". The pattern given on this line will become the left-hand side of a \
function definition, exactly as you would type it if you were creating the \
entire function in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Arguments:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" line specifies the expressions to be passed to the external program. \
These expressions don't have to be the same as the variable names on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Pattern:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" line, although they often will be. You could, for example, put ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["{Abs[i], j^3}",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". The point is that what you put on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Pattern:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line and the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Arguments:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line is ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" code; it will be used verbatim in a definition that could be caricatured \
as follows:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"AddTwo[i_Integer, j_Integer] := \n \
SendToExternalProgramAndWaitForAnswer[{i, j}]"], "Input",
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ArgumentTypes:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ReturnType:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" lines contain special keywords used by mprep to create the appropriate ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPut",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" calls that transfer data across the link.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The details of building the executable from the addtwo.tm and addtwo.c \
source files differ from platform to platform. On Unix, you will usually use \
the mcc script that comes with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". You would use a line like",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[" mcc addtwo.tm addtwo.c -o addtwo"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The steps that mcc performs are as follows: (1) run mprep on the .tm file, \
to create a .tm.c file; and (2) compile and link all the source files, \
including the .tm.c file, specifying to the 'cc' compiler where to find the \
mathlink.h file and the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" library file (named libML.a on Unix machines). It is the .tm.c file that \
contains the mprep-generated C source. Normally, this file is deleted by mcc \
after it has been compiled, but if you want to see what it looks like you can \
prevent its deletion by specifying the -g command-line option to mcc. \
Advanced users of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" can learn a lot by studying this file. On Macintosh and Windows, the \
steps to build the program will be different, and you should consult the \
README file that comes with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"The mcc method is convenient for simple projects, but it has some drawbacks, \
one of which is that it is hard-coded to call the 'cc' compiler. You might \
want to skip mcc altogether and write your own makefile. In that case, you \
will be calling mprep yourself. Here's an example:"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" /math/Bin/MathLink/mprep addtwo.tm -o addtwo.tm.c"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"Note that mprep is not on your Unix path, so you will need to specify the \
full pathname. The MathLink library, libML.a, is also located in the \
math/Bin/MathLink directory, and the mathlink.h file is in \
math/Source/Includes."], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["To use the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["AddTwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" function in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", you launch the external program with the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" function:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["link = Install[\"addtwo\"]"], "Input",
AspectRatioFixed->True],
Cell[OutputFormData["\<\
LinkObject[\"addtwo\", 2, 2]\
\>",
"\<\
LinkObject[addtwo, 2, 2]\
\>"], "Output",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[TextData[{
StyleBox["The function ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["LinkPatterns",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" shows what functions are defined by the external program associated with \
a given link:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["LinkPatterns[link]"], "Input",
AspectRatioFixed->True],
Cell[OutputFormData["\<\
{HoldForm[AddTwo[i_Integer, j_Integer]]}\
\>",
"\<\
{AddTwo[i_Integer, j_Integer]}\
\>"], "Output",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["AddTwo[3,4]"], "Input",
AspectRatioFixed->True],
Cell[OutputFormData["\<\
7\
\>", "\<\
7\
\>"], "Output",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[TextData[{
StyleBox["You may wonder, \"How does the definition for ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["AddTwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" appear in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
"?\" After all, the only thing we've done is start up the kernel, type ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", and suddenly ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" knows about a function called ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["AddTwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". The answer is that the external program sends to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" the definitions for the functions it exports when the link is first \
opened. Here's what such a definition looks like:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["?AddTwo"], "Input",
AspectRatioFixed->True],
Cell[TextData[
"Global`AddTwo\n\nAddTwo[i_Integer, j_Integer] := \n \
ExternalCall[LinkObject[\"addtwo\", 2, 2], CallPacket[0, {i, j}]]"], "Print",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[TextData[{
StyleBox[
"Of course, the programmer never sees any of this process, because it is \
handled at one end by the code that mprep writes and at the other end by the \
",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" code. Most programmers have no reason to care how this feat is performed, \
but you should know that all the code involved is accessible. If you are \
interested, you might want to take a look at a .tm.c file and the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" package Install.m, which resides in the StartUp subdirectory of the \
Packages directory.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData[{
StyleBox["1.2 Using :Evaluate: to Include Accessory ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" Code",
Evaluatable->False,
AspectRatioFixed->True]
}], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"It was mentioned earlier that when the external program is installed it \
sends code to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" to set up the \"",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" side\" of the functions it exports. You can also specify arbitrary ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" code to be sent. You might have some accessory code that your functions \
need to have exist in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". A simple example is usage messages.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["You can specify arbitrary ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" code to be sent to the kernel when your program is installed by using \
another feature of template files, the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Evaluate:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line. Here's an example of specifying a usage message:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :Evaluate: AddTwo::usage = \"AddTwo[i, j] adds two integers.\"\n\n\
:Begin:\n :Function: addtwo\n :Pattern: \
AddTwo[i_Integer, j_Integer]\n :Arguments: { i, j }\n \
:ArgumentTypes: { Integer, Integer }\n :ReturnType: Integer\n \
:End:"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Defining messages is a trivial example of the use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Evaluate:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" lines. Another common use is to make your functions appear in a package \
context. The current behavior of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" is to cause all functions defined in installable programs to appear in \
the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Global`",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" context, not the current ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" context (this behavior may be changed in a future version). This means \
that if you want the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["AddTwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" function to appear in a package context, say ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MyPackage`",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", then you cannot do this:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"BeginPackage[\"MyPackage`\"];\n\nInstall[\"addtwo\"]\n\nEndPackage[]"],
"Input",
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["AddTwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" function will still be put into the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Global`",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" context. The best way to handle this is to put the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["BeginPackage",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" statement into an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Evaluate:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line in the .tm file:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :Evaluate: BeginPackage[\"MyPackage`\"]\n :Evaluate: \
AddTwo::usage = \"AddTwo[i, j] adds two integers.\"\n :Evaluate: \
Begin[\"Private`\"]\n\n :Begin:\n :Function: addtwo\n \
:Pattern: AddTwo[i_Integer, j_Integer]\n :Arguments: { i, j }\
\n :ArgumentTypes: { Integer, Integer }\n :ReturnType: Integer\n \
:End:\n\n :Evaluate: End[ ]\n :Evaluate: EndPackage[ \
]"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Everything that follows an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Evaluate:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" up until the first blank line or line whose first character is not a \
space will be sent as a single unit. This means you need to have a separate ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Evaluate:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" for each separate statement or definition. There is more discussion of \
the use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Evaluate:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" in \nSection 1.9, Large Projects.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["1.3 Putting and Getting Arguments Manually"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Note that in writing the addtwo program and the template, we have not had \
to make a single ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" call. With a little additional effort you can take more control over the \
passing of arguments and return values. This would be necessary, for example, \
if the external function needed to receive or return expression types that \
are not among the set handled automatically by mprep, or if the function \
returned different types of results (such as an integer or the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Failed",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[") in different situations.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"As an example, we will modify the addtwo program so that it works for \
larger integers, up to the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["long",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" integer size. In the template file, the keyword ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Integer",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ArgumentTypes:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ReturnType:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" lines causes mprep to create calls to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetInteger",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutInteger",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", which transfer C ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["int",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["s. Instead, we need to call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetLongInteger",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutLongInteger",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", so we change these two lines:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :ArgumentTypes: { Manual }\n :ReturnType: Manual"], "Special1",\
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The keyword ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ArgumentTypes:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" line informs mprep that we will write our own calls to get the arguments, \
and similarly ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ReturnType:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" line indicates that we will put the result ourselves. Here's how the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function looks now:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" void addtwo(void) {\n \n long i, j, sum;\n\n \
MLGetLongInteger(stdlink, &i);\n MLGetLongInteger(stdlink, &j);\n \
sum = i + j;\n MLPutLongInteger(stdlink, sum);\n }"], "Special1",\
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Note the change in the function's prototype. Remember that the actual call \
to the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" function is made from code that mprep writes, so its arguments and return \
value must match mprep's assumptions, as determined from the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ArgumentTypes:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ReturnType:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" lines of the template. By specifying ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ArgumentTypes:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line, you tell mprep to pass no arguments to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" when it is called. Similarly, by specifying ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ReturnType:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line, you tell mprep to ignore any return value.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["It is possible to use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" on one of these lines and not the other. It is also possible to mix ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" with other types on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ArgumentTypes:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" line. For example, if you want to have the first argument read \
automatically but get the second one yourself, you can write:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[" :ArgumentTypes: { Integer, Manual }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["In this case, the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function would be written to take one ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["int",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" argument, and inside it there would be one call to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetInteger",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". If you use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ArgumentTypes:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line, it must be the last type in the list. In effect, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" means \"I want to get all the remaining arguments from the link myself\". \
You cannot specify",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :ArgumentTypes: { Integer, Manual, Integer }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"It is likely that the arguments you will be passing to your function are \
among the set handled automatically by mprep (integers, reals, lists of \
these, strings, and symbols). In this case it is quite convenient to have \
mprep take care of this part of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" communication. However, I recommend that you manually return results to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". It only takes one line of code to send simple types back, and for any of \
the more advanced ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" techniques described below, you will need to have control over what is \
sent back and when.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["1.4 Passing Lists and Arrays"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Another case where you need to use the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" keyword is when you need to return a list to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" sample program bitops demonstrates this. For our purposes only one of the \
functions defined in bitops.c is relevant: the function ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["complements",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", which takes a list of integers and returns a list of the bitwise \
complements of the integers. Here is the template entry in bitops.tm:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :Begin:\n :Function: complements\n :Pattern: \
BitComplements[x_List]\n :Arguments: {x}\n :ArgumentTypes: \
{IntegerList}\n :ReturnType: Manual\n :End:"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["There is a keyword ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["IntegerList",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" that can be used on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ArgumentTypes:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" line, so you can have mprep get the list for you, but you cannot use it \
in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ReturnType:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line--you have to use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and put the result list yourself. Here is the C function:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" void complements(int px[ ], long nx) {\n\n long i;\n \
int *cpx;\n\n cpx = (int *) malloc(nx);\n for(i = 0; i < \
nx; i++)\n cpx[i] = ~ px[i] ;\n MLPutIntegerList(stdlink, \
cpx, nx);\n free(cpx);\n }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Note that we have specified only one argument, an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["IntegerList",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", to be passed to the external function, but the function itself is \
written to take an integer array followed by a long integer. Confusion over \
this is a source of many user errors. When the mprep-generated code reads the \
list of integers, it will determine the length of the list and pass this to \
your function. Sometimes users mistakenly believe that they must themselves \
pass the length of the list from ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", so they erroneously write the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Arguments:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ArgumentTypes:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" lines like this:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :Arguments: {x, Length[x]}\n :ArgumentTypes: {IntegerList, \
Integer}"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The long parameter that will receive the length of the list always comes \
immediately after the list itself in the arguments to your function. For \
example, if you need to receive a list of integers, a list of reals, and an \
integer, you would write the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ArgumentTypes:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line like this:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :ArgumentTypes: {IntegerList, RealList, Integer}"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["and the function prototype would look like:"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" void func(int ilist[ ], long ilen, double rlist[ ], long rlen, int \
j);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["To put the result list back to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", you can use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutIntegerList",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" or ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutRealList",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"In addition to putting and getting lists of integers and doubles, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" has some new functions for putting and getting multidimensional arrays in \
a single step, for example ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetDoubleArray",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutDoubleArray",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". Check the mathlink.h header file for the complete set. The easiest way \
to describe these functions is to show a sample program. The following is an \
example function that creates an identity matrix of size n:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" void identity_matrix(int n) {\n\n long dimensions[2];\n \
char *heads[2] = {\"List\", \"List\"};\n long depth = 2;\n \
int *mat;\n int i,j;\n\n mat = (int*) calloc(n \
* n, sizeof(int));\n\n for(i=0; iFalse,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The \"",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Array",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["\" functions are similar to their \"",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["List",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["\" counterparts. In a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["PutArray",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function, instead of a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["long",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" length parameter, you pass an array of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["long",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["s giving the length in each dimension. The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["heads",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" parameter is an array of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["char*",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" that give the heads in each dimension (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["List",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" in most cases). If the heads are ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["List",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" in each dimension, you can simply pass ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["NULL",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" in place of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["heads",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Here's a complete example showing the use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetDoubleArray",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutDoubleArray",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". The function transposes a matrix of reals:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :Begin:\n :Function: transpose\n :Pattern: \
MyTranspose[l_?MatrixQ]\n :Arguments: {l}\n :ArgumentTypes: \
{Manual}\n :ReturnType: Manual\n :End:\n\n void \
transpose(void) {\n\n long *dimensions; \n char **heads; \n \
long depth;\n double *data;\n int i, j;\n \
double *tdata; /* put the transposed array here */\n long \
tdimensions[2]; /* reverse of dimensions */\n\n \
MLGetDoubleArray(stdlink, &data, &dimensions, &heads, &depth);\n \n \
tdata = (double*) malloc(sizeof(double)*dimensions[0]*dimensions[1]);\n\n \
for(i=0; iFalse,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Note the call to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDisownDoubleArray",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". Whenever you use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" to receive an object whose size cannot be known at compile time (e.g., a \
string, symbol, list, or array), ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" reads the object into its own memory space and gives you only the address \
of the data. For example, in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetString",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", you pass the address of a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["char*",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["i.e.",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["char**",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["), and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" stuffs the address of the string it received into your ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["char*",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". You'll note that you haven't had to allocate any memory yourself or \
worry about how big the data is. At this point, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" \"owns\" the data, and it is waiting for your permission to free the \
memory that it occupies, which you grant when you call the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDisown",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" functions. Between the time you call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDisown",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", you can only read the data--do not try to modify it in place. If you \
need to do that, allocate your own memory and copy the data into it (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["e.g.",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["strcpy",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[").",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Note that you need to worry about calling ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDisown",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" functions only if you call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" yourself. For strings, symbols and lists that mprep gets automatically \
for you, it takes care of calling the appropriate ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Disown",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" functions after your function returns.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["1.5 Passing Arbitrary Expressions"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" has functions for passing all native C types, along with single- and \
multidimensional arrays. There are times, though, when you need to send or \
receive expressions that do not fit neatly into C types. Your function might \
need to return a list of mixed integers and reals, or a list of lists that is \
not a matrix, or something even more complicated like ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Integrate[x^2, {x,0,1}]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". How do you go about transferring expressions like these?",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"I will focus on returning such expressions from an external function. It \
is less likely that your function would want to receive such expressions. It \
is certainly possible to receive complex expressions, but what would you do \
with them? You'd have to write your own code to analyze them and extract the \
desired information. If you need to deal with complicated expressions in your \
external functions, you'd be better off writing some code on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" side that acts as a \"wrapper\" around your template functions, \
manipulating and decomposing the expressions into meaningful C-size chunks, \
and sending these instead. This type of chore is more easily programmed in \
the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" language.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["You send expressions over ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" in a way that mimics their ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["FullForm",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" representation. There are ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" functions for the necessary \"atomic\" types (integers, reals, strings, \
and symbols), and if you need to put a \"composite\" expression (something \
with a head and zero or more arguments), you use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutFunction",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" to put the head and the number of arguments, then ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPut",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" calls for each of the arguments in turn. For example, to put the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Integrate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" expression above, you would use:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(stdlink, \"Integrate\", 2);\n \
MLPutFunction(stdlink, \"Power\", 2);\n MLPutSymbol(stdlink, \
\"x\");\n MLPutInteger(stdlink, 2);\n MLPutFunction(stdlink, \
\"List\", 3);\n MLPutSymbol(stdlink, \"x\");\n \
MLPutInteger(stdlink, 0);\n MLPutInteger(stdlink, 1);"], "Special1",\
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Of course, if you want to return an expression like this from your \
function, you will need to declare a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" return type in the .tm file.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"A very common error is attempting to put more than one expression from the \
external function. An external function, just like any built-in function, \
cannot return two things. In the earlier examples, we sent complex \
expressions back to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", but always only one of them. Here is an example of this error:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" void return_two(void) {\n \n int i, j;\n\n \
MLGetInteger(stdlink, &i);\n MLGetInteger(stdlink, &j);\n \n \
MLPutInteger(stdlink, i);\n MLPutInteger(stdlink, j);\n }"],
"Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"The two integers returned need to be wrapped in a head of some sort so that \
they become part of a single expression. The put calls need to be written \
like this:"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(stdlink, \"List\", 2);\n MLPutInteger(stdlink, i);\
\n MLPutInteger(stdlink, j);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["1.6 Requesting Evaluations by the Kernel"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The external function can request evaluations by ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" between the time it is called and the time it returns its result. For \
example, you might want ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" to assist you in computing something, or you might want to trigger some \
side effect such as displaying an error message. The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" function ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" is designed for this purpose. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" takes a string argument that will be interpreted by ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" as input. The result will be returned to your function as an expression \
wrapped with the head ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". You should read this ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" from the link whether you care what is in it or not. ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["As an example, let's go back to the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" function and say you want to detect an overflow when adding the two ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["long",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" integers (that is, a sum that is outside the range of a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["long",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["). If an overflow occurs, you want to show an error message in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" and then return the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Failed",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" instead of the sum.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["You can use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" to trigger the message, but how do you get the definition of the message \
into ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" in the first place? You use an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Evaluate:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line in your .tm file:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :Evaluate: AddTwo::ovflw = \"The sum cannot fit into a C long \
type.\""], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function now looks like this: ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" void addtwo(void) {\n\n long i, j, sum;\n\n \
MLGetLongInteger(stdlink, &i);\n MLGetLongInteger(stdlink, &j);\n \
sum = i + j;\n if(i>0 && j>0 && sum<0 || i<0 && j<0 && sum>0) {\n \
MLEvaluate(stdlink, \"Message[AddTwo::ovflw]\");\n \
MLNextPacket(stdlink);\n MLNewPacket(stdlink);\n \
MLPutSymbol(stdlink, \"$Failed\");\n } else {\n \
MLPutLongInteger(stdlink, sum);\n }\n }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["After the call to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" will send back a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" containing the return value of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Message",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" function (which is simply the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Null",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox["). You need to drain this packet from the link, so you call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" (which will return ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["RETURNPKT",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[") and then ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" to discard the contents. If you wanted to read the contents of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", then you would replace ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" with an appropriate series of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" calls. As an example, let's say you wanted to have ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" compute a Bessel function for you. Here's how you would send the request \
and read the result:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLEvaluate(stdlink, \"BesselJ[0, 5.0]\");\n MLNextPacket(stdlink); \
/* a RETURNPKT will be waiting */\n MLGetDouble(stdlink, \
&my_double); /* inside there will be a real */"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", and the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" functions are discussed in more detail in the second chapter of this \
tutorial, where they are used more extensively. ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" is not the only way the external function can send code to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" for evaluation. Anything sent wrapped in the head ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" will be treated in this way. In fact, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" is merely a convenience function whose code just creates the expression ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket[ToExpression[\"the string\"]]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" and sends this to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["After ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" calls your external function, it reads from the link, expecting to find \
the final result. The head ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" tells ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" \"This is not the final answer. Evaluate this and return the result to me \
wrapped in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
". Keep waiting for the final answer.\" In this way, the external function \
can initiate dialogs of arbitrary length and complexity with the kernel \
before it returns.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"If it is most convenient to send the code you need evaluated as a string \
(for example, if the code is known at compile time), you can use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". In some cases, though, it may be easiest to send it as an expression \
wrapped in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". In the above example computing ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["BesselJ",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", it is likely that the arguments to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["BesselJ",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" will be variables in your own program, not constants embedded in a \
string. Rather than constructing a string and sending it with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", you might want to replace the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line with the following lines:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(stdlink, \"EvaluatePacket\", 1);\n \
MLPutFunction(stdlink, \"BesselJ\", 2);\n MLPutInteger(stdlink, \
my_int);\n MLPutDouble(stdlink, my_double);\n \
MLEndPacket(stdlink);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["You read the resulting ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" in the same way as before.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["1.7 Error Handling"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Our ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function is still missing an extremely important aspect of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" programming: error checking. Most ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" functions return 0 to indicate an error has occurred, and you should \
check their return values, at least for the reading functions. If you \
continue to issue ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" calls after an error has occurred, without clearing the error, things \
will no longer work as expected. Specifically, the link simply refuses to do \
anything until you clear the error. Checking for ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" errors is handled for you by the code that mprep writes for any arguments \
that are read automatically. If you don't do any manual getting of arguments, \
then you don't have to worry about error checking. For any ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" calls that you write yourself, it's up to you. ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The exact series of steps you take after an error has been detected \
depends on whether you want to try to recover or not. If an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" call fails, the easiest thing to do is to simply abandon the external \
function call completely and return the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Failed",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
". It would be more informative to trigger some kind of diagnostic \
message. There is a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" function called ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLErrorMessage",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", which returns a string describing the current error, and this string is \
a good candidate for use in an error message to be seen by the user. Here is \
a code fragment that demonstrates how to detect an error, issue a useful \
message, and then safely bail out of the function call. For each ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["-type call in your code, you can wrap it with something like:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" if( !MLGetLongInteger(stdlink, &i) ) {\n char err_msg[100];\n \
sprintf(err_msg, \"%s\\\"%.76s\\\"%s\",\n \
\"Message[AddTwo::mlink,\",\n MLErrorMessage(stdlink),\n \
\"]\");\n MLClearError(stdlink);\n \
MLNewPacket(stdlink);\n MLEvaluate(stdlink, err_msg); \n \
MLNextPacket(stdlink);\n MLNewPacket(stdlink);\n \
MLPutSymbol(stdlink, \"$Failed\");\n return;\n }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Naturally, if you have more than one or two ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" calls in your code, you would want to implement this as a function or \
macro. Upon detecting the error, the first thing you do is call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLClearError",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" to attempt to remove the error condition, and then ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" to abandon the rest of the packet containing the original inputs to the \
function (in case it hasn't been completely read yet). The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["sprintf",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" is used to construct a string of the form",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" \"Message[AddTwo::mlink, \\\"the text returned by \
MLErrorMessage\\\"]\""], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["which is what is sent to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". The gyrations required to produce this string using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["sprintf",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" are a bit clumsy; this is getting close to a case where it would be \
easiest to send the code as an expression rather than a string, as \
demonstrated earlier. The remaining lines are the same as in the previous \
example of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEvaluate",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". The message triggered here, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["AddTwo::mlink",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", needs to be defined in an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Evaluate:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" line in the addtwo.tm file as follows:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" :Evaluate: AddTwo::mlink = \"There has been a low-level MathLink \
error.\n The message is: `1`.\""],
"Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Now let's see these error messages in action. Earlier, we introduced the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["AddTwo::ovflw",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" error message, to be triggered when the two integers can be read from the \
link properly, but their sum is detected to have overflowed:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["AddTwo[2000000000, 1000000000]"], "Input",
AspectRatioFixed->True],
Cell[TextData[
"AddTwo::ovflw: The sum cannot fit into a C long type."], "Message",
Evaluatable->False,
AspectRatioFixed->True],
Cell[OutputFormData["\<\
$Failed\
\>", "\<\
$Failed\
\>"], "Output",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["AddTwo::mlink",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" error is triggered whenever the arguments are not read properly by ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetLongInteger",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", which will be the case if either one is too large to fit into a C ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["long",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" type:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["AddTwo[5000000000, 1]"], "Input",
AspectRatioFixed->True],
Cell[TextData[
"AddTwo::mlink: \n There has been a low-level MathLink error. The message \
is: \n machine integer overflow."], "Message",
Evaluatable->False,
AspectRatioFixed->True],
Cell[OutputFormData["\<\
$Failed\
\>", "\<\
$Failed\
\>"], "Output",
Evaluatable->False,
AspectRatioFixed->True]}, Open]]}, Open]],
Cell[CellGroupData[{Cell[TextData["1.8 Troubleshooting and Debugging"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["If you get either one of these two errors when you try ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install[\"progname\"]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[":",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["LinkOpen::linkf: LinkOpen[progname] failed."], "Message",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"LinkConnect::linkc: LinkObject[progname, 1, 1] is dead; attempt to connect \
failed."], "Message",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"then either the program is not being found, or it is launching and then \
immediately crashing. If you ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" a program that exists but is not properly ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox["-aware, then ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" will hang until you abort it. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" does not interpret the string you give it, and in particular it does not \
search the directories on ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Path",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" (this behavior may change in the future). The directories it does search \
are dependent on factors outside of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", such as the operating system and shell. On Unix, for example, the path \
that is searched is the path inherited by shell processes launched by the \
kernel. You may need to give a complete pathname to the program. To make sure \
that your program is at least minimally able to run, simply launch it from \
the command line (under Unix) or by double-clicking it (Macintosh or \
Windows). You should get a \"Listen on:\" prompt, which you can dismiss, \
followed by a \"Connect to:\" prompt, which you also dismiss, at which point \
the program will exit.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"If your program passes the above test, but otherwise behaves unexpectedly, \
then a few simple debugging techniques will likely pinpoint the error. If the \
program crashes because of something in your computational code, or if it \
exits because you are using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" calls incorrectly, you will probably see the following message:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"LinkObject::linkd: \n LinkObject[progname, 18, 3] is closed; the \
connection is dead."], "Message",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["In most cases, there is a simple error in your ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" code. Most of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" functions return 0 to indicate that an error has occurred. Go back into \
your source and insert statements to check the return values of each ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" function (start with the reading functions--",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", and anything with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" in its name).",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"If you want to run your installable program with a debugger, you will \
generally need to launch it inside the debugger, and then establish a \
connection with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" manually, rather than having ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" launch your program automatically. This issue is discussed in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink Reference Guide",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", along with an example using the Unix gdb debugger. The details differ \
from platform to platform, but the concept is the same. One side of the link \
needs to open in Listen mode, and the other side then uses Connect mode to \
connect to that listening link. Which side does which is not important; in my \
example I reverse the roles in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink Reference Guide",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" example. Begin by launching the program in your debugger. You will get a \
\"Listen On\" prompt, to which you give an arbitrary link name (on Macintosh \
and Windows, these are arbitrary strings, like myLink; on Unix, they will be \
numbers, 5000 for example). Now, switch to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" and type:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["link = Install[\"name\", LinkMode->Connect]"], "Input",
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["where ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["name",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" is the linkname you specified to the \"Listen On\" prompt. Use string \
quotes around the name, even if it is a number (you don't use string quotes \
earlier, when you reply to the Listen On prompt). Note that ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" can take the same sort of arguments that ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["LinkOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" takes. Here, we give a linkname as the first argument (when we want ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" to launch the program, this is just the filename), and specify link \
options as well.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["1.9 Large Projects"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The examples so far have all been single functions. They are a good model \
for the occasional numerical function that you want to incorporate into ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". The potential for installable functions is much greater, though. You can \
create entire packages or sets of packages, implemented in one or more \
external programs, that effectively \"graft\" new capabilities onto the \
kernel. Some special issues arise when considering larger projects based on \
installable programs.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["First, you will undoubtedly need to write some ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" code to go along with your C functions. I suggest writing \"wrapper\" \
functions in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" that perform the handling of options, some processing of arguments and \
error checking, and other tasks that are more easily done in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". These are the functions that are visible to the user, and they then call \
private functions that are the ones named in templates and map directly to \
functions in the external program. You can develop very sophisticated \
interactions between the C and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" code.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Through the use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":Evaluate:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" lines in your .tm file, you can embed your entire package code in the \
program source files, so that there is no separate .m file to be loaded. The \
advantage to this is convenience for users (they can just ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" the program and be ready to go), but the disadvantage is that any \
modification of the package code requires that the program be recompiled. \
Chances are that your users will not be doing this, though, and during \
development you can keep the package code in a separate .m file.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The basic decision is whether you will have the package code embedded in \
the external program, so what the user types is ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install[\"progname\"]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", or have a package (.m) file that calls ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" within it, so what the user types is ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["<False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
". The problem with the latter approach is that users need to either: (1) \
always give the program a predetermined name and always put it someplace it \
will automatically be found by ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", or (2) edit the .m file to reflect what they choose to name the program \
and the pathname where they put it. The advantage to this approach is that it \
makes your program behave more like a seamless extension to the kernel. \
Specifically, the context-handling functions will work correctly with it, so \
that users use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Needs",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" with your package name just like any other package name, and may even be \
unaware that an external ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" program is involved. Having written significant programs that use both \
approaches, I recommend the second method, writing your package code in a .m \
file that calls ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" internally.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"You can embed C code in a .tm file, and it will be passed along unchanged by \
mprep. This means that you don't need a separate .c file, and this is \
convenient if your code is not long or complicated. In fact, all your \
code--templates, package code, and C code--can be included in one .tm file if \
desired. Here is a sample of the suggested structure of such a .tm file:"],
"Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[":Evaluate: BeginPackage[\"MyPackage`\"]\n\n",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[" All of the package code is here, in :Evaluate: sections...\n",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Times"],
StyleBox[
"\n:Evaluate: FirstFunction::usage = \"FirstFunction does...\"\n\n",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[" etc....\n",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Times"],
StyleBox["\n:Evaluate: EndPackage[ ]\n\n",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[" The C code begins:\n",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Times"],
StyleBox["\n#include \"mathlink.h\"\n\nvoid template_func1() { ...\n\n",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[" etc....\n \n Templates begin:\n",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Times"],
StyleBox[
"\n:Evaluate: Begin[\"MyPackage`Private`\"]\n\n:Begin:\n:Function: \
template_func1\n\n",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[" etc....\n",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Times"],
StyleBox["\n:Evaluate: End[ ]",
Evaluatable->False,
AspectRatioFixed->True]
}], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"If you are writing a commercial-quality program, make sure that your \
external functions behave as if they were well-written built-in functions. \
This means, among other things, that they should be abortable, and they \
should return ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox["-style messages for all errors or warning conditions.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["1.10 Special Topics"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData[
"1.10.1 If You Don't Know the Length of the Result"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Notice that you have to specify the number of arguments that will follow \
in every ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutFunction",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" call. Sometimes it is inconvenient to have to know ahead of time the \
number of arguments that you will send. For example, you might be running a \
loop, generating one element of the result list in every iteration, and you \
don't know ahead of time when the loop will end. There are a couple of tricks \
for getting around this problem.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["One method doesn't involve ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" at all--you just allocate enough local storage in your C program to hold \
all the elements, counting them as you place them in this storage, and when \
you are finished you put them on the link in the usual way. This is \
relatively easy, except you have to deal with the hassle of memory management \
in C. You may need to do a lot of allocating and reallocating memory to hold \
the result as it grows, and you need to be sure you free it all before \
returning.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"It would be easier just to send the elements as they are generated. Then \
you would need to allocate only enough storage to hold a single element, \
reusing the same space for each successive element. One way to do this is to \
create a nested list wrapped in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Flatten",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
". If you think about it, you'll see that you never have to make any \
promises about the total number of elements that will appear in the final \
flattened list. Every sublist contains two elements: an integer (in this \
particular example) and another sublist. When all the integers you need have \
been sent, you send two empty lists (to fulfill the final promise of two \
arguments), which will be obliterated by the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Flatten",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". The expression that is sent might look like ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Flatten[{1,{2,{3,{4,{{},{}}}}}}]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", which evaluates to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["{1,2,3,4}",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
". It's actually a bit more complicated, since if you send a list that is \
nested too deeply, you will hit ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox["'s ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$RecursionLimit",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", and trigger an error. The way around this is to temporarily set ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$RecursionLimit",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Infinity",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", which is best done by localizing its value in a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Block",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". Thus, the actual ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" code you will send will look like:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" Block[{$RecursionLimit = Infinity},\n \
Flatten[{1,{2,{3,{4,{{},{}}}}}}]\n ]"], "Input",
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The sequence of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" calls to send this is straightforward:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(stdlink, \"Block\", 2);\n MLPutFunction(stdlink, \
\"List\", 1);\n MLPutFunction(stdlink, \"Set\", 2);\n \
MLPutSymbol(stdlink, \"$RecursionLimit\");\n MLPutSymbol(stdlink, \
\"Infinity\");\n MLPutFunction(stdlink, \"Flatten\", 1);\n \
MLPutFunction(stdlink, \"List\", 2); \n while(not_finished) {\
\n /* Here is the computation that generates the elements of the\n \
result. This would probably be the main computational section\n \
of your function. */\n i = generate_next_element();\n \
MLPutInteger(stdlink, i); /* or whatever the list elements are */\n \
MLPutFunction(stdlink, \"List\", 2);\n }\n MLPutFunction(stdlink, \
\"List\", 0);\n MLPutFunction(stdlink, \"List\", 0);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"This may look complicated, but it's just \"boilerplate\" code that can be \
pasted into your program where necessary."], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["If the elements of the result list are themselves lists, then ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Flatten",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" will not work since it will flatten out the sublists as well. You can use \
",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Level",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" instead in this case. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Level[listOfLists, {-2}]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" extracts those expressions of depth 2 from the nested list, which is what \
you want if the elements of the outer list are simple lists. If they are \
matrices, use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["{-3}",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" as the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Level",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" specification, since a matrix has depth 3.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["This is an interesting example because what you send back to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" is in effect a \"program\", the execution of which produces the results. \
Of course, every ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" expression is a \"program\" and vice-versa, but it is a conceptually \
useful mental leap here. There are lots of other programs you can send that \
will evaluate to the desired list (a method similar to the above could be \
based on ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Join",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
"), and you can even do something as fancy as sending back a program that \
itself reads from the link, collecting the elements until it reads an \"END\" \
marker. Once you start thinking in these terms, a wealth of sophisticated \
interactions become possible.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Another method for dealing with the problem of not knowing ahead of time \
how many elements will be in the result list involves the use of a \"loopback \
link\", and it is described in the next section. This method is the most \
elegant and probably the most desirable, except in cases where the speed of \
the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" transfer is the most important consideration.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["1.10.2 Loopback Links"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Beginning in Version 2.2 of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", a new link mode was introduced--the \"loopback\" mode (joining Launch, \
Listen, and Connect). This link type is quite useful, but underused by ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" programmers. Brief documentation for loopback links can be found in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Major New Features of Mathematica Version 2.2",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" document.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"A loopback link is a link that \"points back\" at you. You both write to \
and read from it. You can think of it as a U-shaped track onto which you can \
place expressions for storage and later examination or retrieval. If you \
think about it, you'll see that loopback links effectively give the C \
progammer a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" expression \"type\".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"There are a lot of interesting things you can do with loopback links, but \
I will focus on one application of great use in installable programs. This is \
to solve the problem discussed in the previous section: how to send an \
expression (like a list) back to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" when you don't know in advance how many arguments it will have. The \
loopback link provides a very simple solution--as you generate the elements \
of the result list, put them on a loopback link, not the link back to the \
kernel, counting them as you go. Then when it comes time to send them to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", you know how many there are, and you can specify this when you use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutFunction",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" to put the enclosing ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["List",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The loopback link method for solving this problem has an additional \
advantage over the nested list method mentioned in the last section. It may \
be that during the generation of the result list you encounter an error \
condition or some other circumstance where you no longer want to send the \
list at all (you might want to send the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Failed",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" instead, and you might want to trigger an error message). If you are \
putting the result on a loopback link, you don't send anything to the kernel \
until the computation is finished, and you can decide at that time to send \
whatever you want.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"You open a loopback link in the usual way, except you specify \"loopback\" \
as the linkmode. Let's look at a complete function that returns a list of \
integers to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" by first placing them on a loopback link.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" void foo(void) { \n \n int i, num_elements;\n char \
loopback_argv[3] = {\"-linkmode\", \"loopback\", NULL};\n MLINK \
loopback;\n\n loopback = MLOpen(2, loopback_argv);\n if(!loopback) \
{\n /* might want to issue a message as well */\n \
MLPutSymbol(stdlink, \"$Failed\");\n return;\n }\n \n \
num_elements = 0;\n while(some_test) {\n i = \
generate_next_element();\n MLPutInteger(loopback, i);\n \
num_elements++;\n }\n\n MLPutFunction(stdlink, \"List\", \
num_elements);\n for(i=1; i<=num_elements; i++) \
MLTransferExpression(stdlink, loopback);\n \n MLClose(loopback);\n \
}"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Note the use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLTransferExpression",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" to move the integers from the loopback link to the kernel link. This \
function is described in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Major New Features of Version 2.2",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" document. It provides a very convenient means for moving expressions from \
one link to another, since you don't need to be concerned with the exact \
structure of each expression. The destination link is given first, the source \
link second.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The above method is similar to storing the integers in memory allocated \
and maintained by you in your C program. The advantage of using a loopback \
link is that you let ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" deal with all the memory-management issues. There are no calls to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["malloc",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["realloc",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" or ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["free",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", or checks for writing past the end of your allocated storage. Memory \
management would not be difficult in the case of a list of integers, but if \
you were accumulating a list of strings or functions, it would be a big \
chore, with many possibilities for memory leaks and other bugs.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["I cheated a bit, though, in not checking for errors in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPut",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" calls onto the loopback link. An ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPut",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" might trigger a memory allocation inside ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", which could conceivably fail. You don't really need to worry about this \
when writing to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["stdlink",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", the link to the kernel, because that link is being drained by the other \
side as you pour data into it. A local link will require enough memory to \
hold all the data at once, so you should check for errors in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPut",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" calls if you are storing a lot of data.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["1.10.3 Making Your Function Abortable"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"If your function takes significant time to execute, you will want to make it \
abortable. That is, when the user types the usual abort key sequence \
(Control-C in Unix, Command-period on Macintosh, etc.), the function should \
terminate as quickly as possible and return something appropriate."], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"To understand how this is done, you need to know that a link actually \
contains two separate \"channels\" of communication. One channel is for the \
expressions being sent back and forth, and the other one is for urgent \
messages that need to be sent out of sequence with the flow of expressions. \
Examples are requests to interrupt or abort execution. This second channel is \
the one that is managed by the \"",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Message",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["\" functions in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[": ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutMessage",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetMessage",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", and a few others. Don't confuse these with the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLErrorMessage",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function (which returns a string describing an internal ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" error), or the familiar ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" error messages.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Normally, programmers writing installable functions don't need to worry \
about the low-level details at all. Handling messages from the kernel is \
performed in code that mprep writes for you. All you need to know is that \
there is a global variable ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLAbort",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" in installable programs whose value will reflect whether or not the user \
has requested that the function be aborted. If you are running a \
time-consuming loop, you should periodically check the value of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLAbort",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". If it is non-zero, then you should bail out as quickly as possible.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["What should your function return to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" if the user aborts the evaluation? A quick answer might be the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". Indeed, this is what the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink Reference Guide",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" suggests, and this is what your function will return if you do not use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" as the return type in the template, because then it is the \
mprep-generated code that takes care of sending the final answer to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". That code checks the variable ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLAbort",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", and if it is set, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" is sent no matter what your function returns.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["However, sending ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" is probably not the ideal behavior. After all, when the user aborts a \
calculation that does not involve an external function, the entire evaluation \
aborts, and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" is returned as the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Out[]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" value. It is not the case that whatever function was executing at the \
time the abort was requested returns ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". That is, if you evaluate ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["f[g[x]]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", and you abort during the execution of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["g[x]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", you don't get ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["f[$Aborted]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" as the result. Unfortunately, if ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["g",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" was an external program that returned ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", this is what you would get. If you're writing a program that involves \
calling external functions, you don't want to worry that an expression deep \
inside your code is going to evaluate to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" instead of something meaningful simply because the user tried to abort at \
an inopportune time!",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[" While the external function is executing, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" captures abort requests and sends them to the function as ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" messages. As a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" programmer, if you want your functions to behave like built-in ones, it \
is your responsibility to \"propagate\" the abort request back to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
"'s normal abort-processing mechanisms, which are restored when the \
external function returns. You do this by returning not the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", but rather the function ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Abort[]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". If you return ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Abort[]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", then ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" will halt the entire evaluation no matter how deep inside it, just like \
it does with programs written entirely in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The fact that the abort behavior of mprep-generated code is not ideal is \
another reason to routinely use the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" return type and put the result to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" yourself.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Earlier, I said that all you need to know is that there is a global \
variable ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLAbort",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" in installable programs. This isn't strictly true, however--there is one \
more detail you need to be aware of. On systems without preemptive \
multitasking (Macintosh and Windows), your function needs to yield the \
processor so that the kernel has a chance to actually send the abort message \
to you. You could write calls to an appropriate function depending on the \
platform (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["e.g.",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", on Macintosh, call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["WaitNextEvent",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
"), but there is an easier solution that will keep your code portable \
between systems. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" supports something called a yield function, which is discussed more fully \
in Section 2.5.2. For now, simply note that template programs define and \
install a yield function (it is written by mprep) that calls the appropriate \
function to yield the processor temporarily to other programs. Therefore, you \
can simply call the yield function periodically during your calculation.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Note that many ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" functions call the yield function themselves internally (including the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Put",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
"-type calls). Therefore, you don't need to worry about calling the yield \
function if you are making ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPut",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" calls during your computation (for example, if you are putting pieces of \
the result on the link periodically during your calculation). You need to \
call the yield function only if your function doesn't make any ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPut",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" calls before checking the value of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLAbort",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". You also don't need to do it if you are running under Unix (but you \
might want to, for portability reasons).",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Here is a skeleton of a template program that performs a long calculation \
and periodically checks ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLAbort",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". Note that ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLCallYieldFunction",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" is new in Version 2.2.2, and don't worry about what the arguments \
mean--just copy the code exactly as it appears below.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" void long_function(void) { \n \n int result = 1;\n \
\n while(some_test && !MLAbort) {\n result = \
perform_computation(result);\n \
MLCallYieldFunction(MLYieldFunction(stdlink), stdlink,\n \
(MLYieldParameters)0 );\n }\n\n if(MLAbort) {\n \
MLPutFunction(stdlink, \"Abort\", 0);\n /* Contrast with: \
MLPutSymbol(stdlink, \"$Aborted\"); */\n } else {\n \
MLPutInteger(stdlink, result);\n }\n }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["What if you are sending elements of a result list to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" as you go, so that when you detect an abort you have already sent a \
partial answer? You cannot \"take back\" what you've sent and send something \
else (like ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Abort[]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[") instead. However, if you simply call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEndPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" in the middle of sending an expression (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["i.e.",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", at a place where ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEndPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" is illegal), ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" will get the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" by default.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"In summary, a time-consuming function should periodically check the value \
of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLAbort",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". You might need to call the yield function periodically, to allow the \
kernel process to send the abort message to you. If you are putting the \
result back to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" manually, you should send the function ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Abort[]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" and return. If you are not using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Manual",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" on the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[":ReturnType:",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" line of the template file, then you should immediately return a value \
from your function (it can be garbage, since it will not be sent to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" anyway). The mprep-generated code will send ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" in its place. Finally, if you have already sent part of the result by the \
time you detect the abort, you should just call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEndPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", which will cause ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" to get the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Aborted",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" by default.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]]}, Open]]}, Open]],
Cell[CellGroupData[{Cell[TextData[{
StyleBox["2. Calling the ",
Evaluatable->False,
PageBreakAbove->True,
AspectRatioFixed->True,
FontSlant->"Plain"],
StyleBox["Mathematica",
Evaluatable->False,
PageBreakAbove->True,
AspectRatioFixed->True],
StyleBox[" Kernel from External Programs",
Evaluatable->False,
PageBreakAbove->True,
AspectRatioFixed->True,
FontSlant->"Plain"]
}], "Subsubtitle",
Evaluatable->False,
PageBreakAbove->True,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" to \"install\" external programs into ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" is very useful, but it only scratches the surface of what can be done. \
The real power of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" is that you can add the computational and programming services of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" kernel to your own programs. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" is not just a way to control the kernel, it is ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["the",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" way. When you use the standard \"notebook front end\" that ships with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", you are using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" in this way. There is no privileged communication between front end and \
kernel--everything takes place via the same open, documented set of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" functions that is available to all programmers.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" to drive the kernel is more complex than writing installable functions \
because you have to write all the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" code yourself, and you will be having more complicated interaction with \
the kernel. ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"It is important to remember that you do not use the kernel as if it were a \
compiled library of mathematical routines. Rather, you are interacting with a \
separate program that has its own thread of execution. You will be running \
the kernel in so-called \"mathlink mode\", which means that all the kernel's \
input will come from your program, all its output will be directed to your \
program, and all communication will take place in the form of \"packets\". \
You have to know the proper way to send expressions to the kernel, what type \
of results to expect back, and how to read them off the link."], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Two useful resources you might not be aware of are available on ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathSource",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". The first is the Macintosh program Link Tutor, written by this author, \
which gives you a point and click interface for executing ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" functions. You can execute ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" functions one at a time in an interactive session and see the results. It \
is a good tool for learning what types of packets the kernel will send you \
under certain conditions, in what order, and what their contents are. The \
other resource is frontend.c, a small C program that implements a more or \
less complete terminal-like interface to the kernel. This is a good place to \
see code for reading out the contents of all of the packet types you might \
get from the kernel.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["2.1 A Simple Program"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"Let's look at a simple example of a program that uses the kernel for \
computation. This program will launch the kernel, have it calculate the sum \
of two integers, then close it and quit. We will look at these specific \
programming techniques in detail later; for now note the general idea and how \
simple it is."], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" #include \n #include \"mathlink.h\"\n\n int main(int \
argc, char * argv[ ]) {\n\n int i, j, sum;\n MLINK lp;\n\
int pkt;\n MLEnvironment env;\n\n printf( \
\"Enter two integers:\\n\\t\" );\n scanf( \"%d %d\", &i, &j);\n\n \
env = MLInitialize(NULL);\n if(env == NULL) return 1;\n \
lp = MLOpen(argc, argv);\n if(lp == NULL) return 1;\n\n /* \
Send Plus[i, j] */\n MLPutFunction(lp, \"Plus\", 2);\n \
MLPutInteger(lp, i);\n MLPutInteger(lp, j);\n \
MLEndPacket(lp);\n\n /* skip any packets before the first \
ReturnPacket */\n while (MLNextPacket(lp) != RETURNPKT) \
MLNewPacket(lp);\n\n /* inside the ReturnPacket we expect an integer \
*/\n MLGetInteger(lp, &sum);\n\n printf( \"sum = %d\\n\", \
sum);\n MLClose(lp);\n MLDeinitialize(env);\n return \
0;\n }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.2 Opening a Link to the Kernel"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["2.2.1 MLOpen"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" function that opens a link is ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". There are a lot of details about how links are opened, what protocols \
are used, and so forth, that are treated in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink Reference Guide",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". I will just briefly discuss some of the main points. You can use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" to launch the kernel directly from your program, and this is probably \
what you will most often want to do. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" takes an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["argc/argv",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" pair of arguments, like the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["main",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function of a C program. This is so you can pass the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["argc",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["argv",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" originally passed to your program directly into ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", allowing the user to specify arguments for the link when they launch \
your program. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" will ignore command line arguments that do not make sense to it, so you \
don't have to worry about interference from arguments that you want your own \
",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["main",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" function to use. A typical Unix command line to launch a program that \
will itself launch a kernel might look like this:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" myprog -linkname 'math -mathlink' -linkmode launch"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Note that 'math -mathlink' must be quoted so that it is sent to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" as a single argument (the -mathlink is an argument to math, so in effect \
there is a command line within the command line). Alternatively, you can just \
hard-code the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["argv",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" array in your program like this:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" int argc = 4;\n char *argv[5] = {\"-linkname\",\n \
\"math -mathlink\",\n \"-linkmode\",\n \
\"launch\",\n NULL};"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"The advantage of allowing the user to specify the link options on the \
command line is that they might want to use a linkmode other than 'launch', \
or perhaps they will need to specify a different name for the kernel program \
than just 'math'. Of course, you can query the user for link arguments \
through prompts or a dialog box if you wish, instead of reading the command \
line."], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"The above example was typical for Unix. On the Macintosh, the link name will \
normally look a bit different, perhaps the following:"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" int argc = 4;\n char *argv[5] = {\"-linkname\",\n \
\"'Hard Disk:Math 2.2:Mathematica Kernel' -mathlink\",\n \
\"-linkmode\",\n \"launch\",\n \
NULL};"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Notice the very important inner set of single quotes around the pathname. \
Because Macintosh folder and file names can have spaces in them, it is \
important that the pathname be enclosed in single quotes so it is seen inside \
",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" as a single string, not separate chunks broken up by spaces.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"In Windows, don't forget that C treats the '\\' character specially in \
string constants. If you are embedding filenames into your code, make sure \
you use two consecutive '\\' to indicate a directory separator, as in this \
example:"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" int argc = 4;\n char *argv[5] = {\"-linkname\",\n \
\"c:\\\\wnmath\\\\math -mathlink\",\n \"-linkmode\",\n\
\"launch\",\n NULL};"], "Special1",\
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.2.2 MLConnect"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["If ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" fails, it will return ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["NULL",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". However, the fact that ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" returns non-",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["NULL",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" does not mean that the link is connected and functioning properly. There \
are a lot of things that could be wrong. For example, if you launch a program \
that knows nothing about ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" will still succeed. There is a difference between opening a link (which \
involves setting up your side) and connecting one (which verifies that the \
other side is alive and well).",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["If the link cannot be connected, then the first ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" call you make that tries to read or write something will fail, or worse, \
hang indefinitely. Rather than put some special-case test on your first \
reading or writing function (which may be physically quite distant in your \
code from the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" call), you might want to call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLConnect",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" after ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLConnect",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" will try to connect the link without actually reading or writing \
anything, and it's a convenient, self-documenting way of ensuring that the \
link is functioning properly before proceeding with your program. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLConnect",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" takes a link object as its argument, and returns non-zero to indicate a \
successful connection.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["It's important to note that the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLConnect",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" function will block until the connection succeeds or until it detects a \
fatal problem with the link. Thus, your program will hang during the startup \
time of the kernel (if you call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLConnect",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" immediately after ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLOpen",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
"). A more serious problem is that if the user mistakenly launches a \
program that is not ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox["-aware, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLConnect",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" will block indefinitely. Dealing with blocking in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" functions is discussed more thoroughly later, but for now note that there \
are two strategies: installing a yield function or polling ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLReady",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". The use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLReady",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" deserves special comment in the present context. Before the link is \
connected, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLReady",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" has a special meaning: it tells whether the other side is ready to \
participate in a connection. In other words, it tells whether ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLConnect",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" will block or not. Thus, before you call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLConnect",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", you can repeatedly call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLReady",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", waiting for it to return ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["TRUE",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", and perhaps bail out of the attempt to connect after some period \
elapses.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.2.3 Using Listen and Connect LinkModes"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"You do not have to launch the kernel in your program. If it is already \
running, users can establish a connection to your program manually. This is \
done using the Listen and Connect link modes. One side must open a link in \
Listen mode, and the other opens a link with Connect mode, specifying the \
listening link to connect to. For example, your program can open a listening \
link, announcing to the user what \"name\" is being broadcast (or letting the \
user pick a name), and then the user can manually connect to that link from ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". For example, if you opened a link on a Macintosh with this ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["argv",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" array:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" char *argv[5] = {\"-linkname\",\n \"myLink\",\n \
\"-linkmode\",\n \"listen\",\n \
NULL};"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["then the command in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" to connect to that link would be the following:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["LinkOpen[\"myLink\", LinkMode->Connect]"], "Input",
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"At this point, the connection will be established so that expressions can \
be read and written on each end, but the kernel is still functioning in its \
normal interactive mode; it has not become a \"slave\" to your program (it is \
not yet in \"mathlink mode\"). To point the kernel's attention toward your \
program, you need to set the kernel's ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$ParentLink",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" variable to be the link to your program:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"$ParentLink = %;\n\n(* or, just do it in one line:\n $ParentLink = \
LinkOpen[\"myLink\", LinkMode->Connect]\n*)"], "Input",
AspectRatioFixed->True],
Cell[TextData[
"When you use the Launch linkmode, all this is taken care of for you."],
"Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"As an experiment, some time when you are using the front end, type ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$ParentLink = Null",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
". This will \"unattach\" the master/slave relationship between front end \
and kernel. On Macintosh or Windows, you will see the kernel's \
terminal-interface window appear in the background. Switch to it, and you \
will see that you can now interact with it as if you had launched it by \
itself, instead of from the front end. In the kernel window, type ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$ParentLink = First[Links[]]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" (this will point ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$ParentLink",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" back at the link to the front end, which is still open). Switch back to \
the front end, and you should be able to continue with your session.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.2.4 MLInitialize and MLDeinitialize"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["In the sample program above there is a call to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLInitialize",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" before the link is opened. Starting with Version 2.2.2, all correct ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" programs must call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLInitialize",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" before making any ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" calls, and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDeinitialize",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" after closing all opened links. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLInitialize",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDeinitialize",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" have never been documented before Version 2.2.2, so it is likely that all \
existing ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" programs do not call them. Does this mean that every existing ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" program is suddenly broken when built with version 2.2.2 of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" libraries? Technically yes, but in practice there will rarely be a \
problem. If you are the author of a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" program that you distribute in source code form, you should update the \
code to call these two functions. If you are currently writing a program, \
make sure it calls them (this change is backward compatible with older \
versions of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[").",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Note that this is not a concern when writing \"installable\" functions \
(treated in the first chapter of these notes). With installable functions, \
the mprep tool writes most of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" code, including calls to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLInitialize",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDeinitialize",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Here is how to use them. Declare a variable of type ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEnvironment",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and assign it the return value from ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLInitialize",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". Then pass this variable to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDeinitialize",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" before your program exits.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLEnvironment env;\n \n ...\n \n env = \
MLInitialize(NULL);\n if(env == NULL) clean_up_and_exit();\n link = \
MLOpen(....);\n \n ...\n \n MLClose(link);\n \
MLDeinitialize(env);\n return;"], "Special1",
Evaluatable->False,
AspectRatioFixed->True]}, Open]]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.3 Sending Expressions to the Kernel"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The things you send with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" are ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["expressions",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", not just strings or numbers or some other limited type. Since everything \
in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" is an expression, you have its full power and expressiveness at your \
disposal. There are two classes of expressions in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
": \"atomic\" expressions, which have no subparts (these are strings, \
symbols, and numbers), and \"composite\" expressions, which have a head and \
zero or more arguments. Composite expressions are things you would write with \
square brackets, such as ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["f[]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["h[x, y]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["{1,2,3}",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" (which is a shorthand for ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["List[1,2,3]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox["), ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["2+2",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" (which is a shorthand for ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Plus[2,2]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox["), and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Integrate[x^2, {x,0,1}]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". There are ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPut",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" functions for the necessary atomic types (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutString",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutSymbol",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutInteger",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", etc.), and for composite expressions you use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutFunction",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". You send expressions using these ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPut",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" calls in a way that mirrors their ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["FullForm",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" representation in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". Thus, to send the expression ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["{1.23, f[x], {5, \"a string\"}}",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", you would say:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(link, \"List\", 3);\n MLPutReal(link, 1.23);\n \
MLPutFunction(link, \"f\", 1);\n MLPutSymbol(link, \"x\");\n \
MLPutFunction(link, \"List\", 2);\n MLPutInteger(link, 5);\n \
MLPutString(link, \"a string\");"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"If you aren't sure what sequence of calls is required for some expression, \
just launch ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", type in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["FullForm[Hold[expression]]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", and the output can be translated directly into the appropriate calls. \
Ignore the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Hold",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" that will be wrapped around the output--it is included merely to prevent \
the expression from evaluating (you want to see the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["FullForm",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" of the original expression, not of what it evaluates to).",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"I mentioned earlier that when the kernel is in \"mathlink mode\", it sends \
all results in the form of packets, and expects all input in packets. (The \
use of the term \"packet\" here should not be confused with the concept of \
packets that might exist in some low-level communication protocol; TCP/IP \
packets, for example. The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" programmer need have no concern over such low-level issues.) ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" packets are simply functions, \"heads\" that serve to convey to the \
receiving side of the link some information about what to do with the \
contents. When the kernel sends back the result of computing ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["2+2",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", it sends back the answer wrapped in the do-nothing function ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[":",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["ReturnPacket[4]"], "Input",
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" wrapper tells your program that the content is the result of an \
evaluation.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData[{
StyleBox["2.3.1 Packets for Sending Things to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"]
}], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"Everything that you send to the kernel should be wrapped in a packet head. \
There are three packet types for sending things to the kernel."], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" \"main loop\"",
Evaluatable->False,
AspectRatioFixed->True]
}], "Subsubsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"To appreciate the difference between the various packets, you need to \
understand the concept of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox["'s \"main loop\". When you use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" in the usual way, each input string you type is fed through a main loop \
that begins with parsing the string into an expression, evaluating the \
expression, and finally turning the resulting expression back into a string \
for printing to the screen. An accounting of the steps in the main loop is \
given in Appendix A.7.3 of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["The Mathematica Book",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". The steps include application of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$PreRead",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Pre",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$Post",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$PrePrint",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" functions, and most importantly, assigning the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["In",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Out",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" values.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The main loop is designed to implement the notion of an interactive \
\"session\", with a history of inputs and outputs recorded in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["In",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Out",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" values. For your use of the kernel, such a notion may be superfluous. If \
you are just using it for computational services, you may have no reason to \
want a running history of previous inputs and outputs. In this case, you want \
to circumvent all the steps in the main loop except the actual evaluation of \
the expression. On the other hand, if you are creating your own front end \
that a user interacts with, you mght want to display the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["In",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Out",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" prompts, or at least provide a way to recall previous input and output.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The three packet types differ in the form of their contents, the form of \
the results returned the kernel, the number and type of packets you will get \
back, and whether the main loop will be run. \nAs an example, if the main \
loop is run, you will always get an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InputNamePacket,",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" and perhaps also an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["OutputNamePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", with each evaluation.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["EvaluatePacket"], "Subsubsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The contents of an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" are an arbitrary ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" expression, which will be evaluated and the result sent back to you as an \
expression wrapped in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". The main loop is circumvented.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Here is how you would send ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["3+3",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[":",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(lp, \"EvaluatePacket\", 1);\n MLPutFunction(lp, \
\"Plus\", 2);\n MLPutInteger(lp, 3);\n MLPutInteger(lp, \
3);\n MLEndPacket(lp);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["You may have seen or written ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" code that did not explicitly use a packet head for sending things. In the \
past, if you left off a packet head, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" was assumed. Be aware that this behavior is no longer supported; always \
use a packet head and an explicit call to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLEndPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". Note that there is no \"",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
"\" for sending the packet head--since packets are just functions, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPutFunction",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" is used. ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Building up complicated expressions with a series of these calls is \
straightforward, but it can be very tedious. Another way to send something to \
",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" is as an input string wrapped in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ToExpression",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" function:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(lp, \"EvaluatePacket\", 1);\n MLPutFunction(lp, \
\"ToExpression\", 1);\n MLPutString(lp, \"3 + 3\");\n \
MLEndPacket(lp);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["For sending ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["3+3",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" this isn't any easier, but for something like ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Plot3D[Sin[x] Cos[y], {x,0,2Pi}, {y,0,2Pi}]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" it saves a lot of code. You should use this method whenever it is more \
convenient to send code as a string (for example if you know it at compile \
time, or if you are reading the input from a file or keyboard).",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Keep in mind that what you are sending to the kernel is ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" code in all its generality. Anything that's possible to type into a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" session can be sent via ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". It may be a bit clumsier to create expressions with sequences of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLPut",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" calls, but keep separate in your thinking the code you want the kernel to \
execute and the details of \"assembling\" that code in your C program.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Say you want not only to send the code as a string, but also to receive \
the result as a formatted string, exactly as it is displayed in a normal \
interactive ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" session. You would do this if you wanted to display the result to the \
user (i.e., with all the complicated line-breaking logic for having \
multi-line expressions formatted properly). You need merely ask yourself how \
you would write ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" code that would take a string, turn it into an expression, evaluate it, \
and then turn the result back to a string. That code is simply",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData["ToString[ToExpression[\"the string\"]]"], "Input",
AspectRatioFixed->True],
Cell[TextData[
"The series of functions to assemble this expression and send it from your C \
program follows directly:"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(lp, \"EvaluatePacket\", 1);\n MLPutFunction(lp, \
\"ToString\", 1);\n MLPutFunction(lp, \"ToExpression\", 1);\n \
MLPutString(lp, my_string);\n MLEndPacket(lp);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["EnterTextPacket"], "Subsubsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The contents of an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" must be a string, which will be sent through the entire main loop, \
beginning with parsing as ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" input. The result of the evaluation will be sent back to you as a \
formatted string wrapped in a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". Since the main loop is run, you will also get an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InputNamePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", and possibly an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["OutputNamePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". You will not get an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["OutputNamePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" if the calculation returns ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Null",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" (because ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" doesn't give output prompts for ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Null",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" return values). Note that the last thing you will get is the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InputNamePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", because it is the prompt for the next input, not the one you just sent. \
In other words, the signal that ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" is finished dealing with your last input is the arrival of an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InputNamePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" is not discussed in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink Reference Guide",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", but causes the same behavior as using the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Enter",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" function, and this function is documented. That is, the following two \
fragments are equivalent:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(lp, \"EnterTextPacket\", 1);\n MLPutString(lp, \
\"2 + 2\");\n MLEndPacket(lp);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" /* OBSOLETE... */\n MLPutFunction(lp, \"Enter\", 1);\n \
MLPutString(lp, \"2 + 2\");\n MLEndPacket(lp);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Enter",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" is now obsolete. Always use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" instead.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" is what Wolfram Research's own front ends use for sending user input \
(which is nothing more than a string of characters when typed in) to the \
kernel. In future versions of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" this may change, but the point is that if you want to implement an \
interface that is similar to what the standard front ends present (accept \
user input as a string and print out formatted output as a string, with \
prompts), you can send input to the kernel as a string wrapped in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
". It is possible to implement a primitive interface that looks very much \
like the kernel-only \"terminal interface\" with just a small number of lines \
of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" code by using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", which is exactly what is done in frontend.c example program, available \
on ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathSource",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["EnterExpressionPacket"], "Subsubsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["EnterExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" is like ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" in that the main loop is run, except that the contents of an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" must be an expression, not a string to be parsed as code. Furthermore, \
the result is sent back to you as an expression wrapped in a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(lp, \"EnterExpressionPacket\", 1);\n \
MLPutFunction(lp, \"Plus\", 2);\n MLPutInteger(lp, 2);\n \
MLPutInteger(lp, 2);\n MLEndPacket(lp);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Actually, when you use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", only a subset of the main loop is run. There are some steps at the \
beginning of the main loop that occur before the input string is parsed into \
an expression (application of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$PreRead",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" function is an example). With ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", you in effect bypass the parsing step because what you send is already \
an expression. Similarly, there is a step at the end of the main loop that \
converts the result expression to a string for display on the screen (the \
application of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["$PrePrint",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" function). This step never occurs with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", since what is sent back is the result still in the form of an \
expression.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]]}, Open]],
Cell[CellGroupData[{Cell[TextData[
"Summary of Packet Types for Sending to the Kernel"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["There are only three packet types: ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
". These packet types differ in whether their contents are to be an \
expression or a string, whether their results are to be returned as an \
expression or a string, and whether they implement the kernel's so-called \
\"main loop\".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"The one you choose will depend on the answers to the following questions: "],
"Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData[
"Do you want the main input/output loop to be run?"], "Subsubsection",
CellDingbat->None,
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Ask yourself whether you or your users will ever need to refer directly to \
previous input or output. If the answer is no, then use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" for sending things to the kernel, which bypasses the main loop. If the \
answer is yes, then use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" or ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" (the \"Enter\" in their names conveys the property of running the main \
loop).",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData[
"Do you want to send input as a string or as an expression?"], "Subsubsection",\
CellDingbat->None,
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"As mentioned earlier, if you are letting users type input for the kernel, \
or if you know at compile time some code you want to send, it is easiest to \
send the code as a string. If you will be using an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" (based on your answer to the previous question), you can send a string as \
follows:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(lp, \"EvaluatePacket\", 1);\n MLPutFunction(lp, \
\"ToExpression\", 1);\n MLPutString(lp, \"some string of \
Mathematica code\");\n MLEndPacket(lp);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"If you have decided that you want the main loop, you will be using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" or ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", and the choice between these is whether you want to send a string or an \
expression.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData[
"Do you want to receive output as a string or as an expression?"],
"Subsubsection",
CellDingbat->None,
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["If you are using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" and want to get the result back as a string, use this:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(lp, \"EvaluatePacket\", 1);\n MLPutFunction(lp, \
\"ToString\", 1);\n MLPutFunction(lp, \"ToExpression\", 1);\n \
MLPutString(lp, \"some string of Mathematica code\");\n \
MLEndPacket(lp);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["If you use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" the result will always be a string, and with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", it will be an expression, although you can force the result expression \
into a string in the same way as with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", by wrapping the input expression with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ToString",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" when you send it:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(lp, \"EnterExpressionPacket\", 1);\n \
MLPutFunction(lp, \"ToString\", 1);\n MLPutFunction(lp, \"Plus\", \
2);\n MLPutInteger(lp, 3);\n MLPutInteger(lp, 4);\n \
MLEndPacket(lp);"], "Special1",
Evaluatable->False,
AspectRatioFixed->True]}, Open]]}, Open]]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.4 Receiving Expressions from the Kernel"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData[
"2.4.1 Reading Packets: MLNextPacket and MLNewPacket"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Everything the kernel sends to you will be wrapped in a packet. As \
mentioned earlier, packets are just functions from the kernel's perspective. \
Their purpose is to convey to you information about what is inside, whether \
you might be interested in it, and how to read it. You can read packets with \
",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetFunction",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" if you want to, but this would be inconvenient. Instead, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" has two special functions for manipulating incoming packets: ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". Their names are confusingly similar, but their actions are quite \
different. Think of packets as boxes, and the kernel as sending you a \
stream of boxes on a conveyor belt. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" opens a box, whereas ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" discards an already-opened box. Once you have opened a box with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", you must either read out its entire contents, or abandon it with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". It is an error to call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" at any time other than when you are \"between\" boxes, either because you \
have completely emptied the last one or because you threw it away with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" has only one effect--to abandon already-opened boxes. If you call it \
between boxes, it does nothing. That is important to remember because it \
means it is always safe to call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" more than once. If you encounter a condition where you know you are not \
interested in any data that might be left in a packet, or you want to make \
sure that you are currently between packets, you can call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" without worrying if it has already been called.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" returns one of a set of predefined integer constants to indicate the type \
of packet that was opened. These constants are defined in mathlink.h, and \
have names like ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["RETURNPKT",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["RETURNTEXTPKT",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["INPUTNAMEPKT",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", etc. If you are implementing a sophisticated \"front end\" for the \
kernel, you will typically have a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["switch",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" statement in your main loop that tests the value of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" and branches to code appropriate for reading the contents of the various \
packet types. You will need to do this if you are allowing the user to enter \
arbitrary ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" code, so you need to be prepared to receive virtually any kind of packet \
type. For example, the user might execute the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InputString",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" function, which prompts for an input from the user. If this happens, your \
program will receive an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InputStringPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" from the kernel, which is a signal that you need to display a dialog box \
or other prompt to get input and then send back a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["TextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" with the reply. The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InputString",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" function is rarely used, of course, and most of the time you'd only be \
sending and receiving a handful of common packets, but if you are going to \
give the user a way to enter ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" code you need to be prepared for anything. An excellent reference for \
handling the entire set of packets is the frontend.c sample program, which \
can be found on ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathSource",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"For many uses, though, you are only interested in some limited interaction \
with the kernel (like using it strictly for computational services), where \
you know the types of things you will be sending, or at least where you know \
the types of results you are interested in (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["e.g.",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", you don't have to worry about displaying kernel messages, or the results \
of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Print",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" statements, or graphics). In these cases, you will simply be discarding \
most packets. Typically, you will only be interested in one packet type, the \
result of a computation, which will usually be a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" (depending on how you sent the computation in the first place, as \
discussed in Section 2.3). This is what was done in the example program in \
Section 2.1. In this case, you want to implement the logic, \"for every \
packet that is not a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", throw it away\". That is coded as follows:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" while (MLNextPacket(link) != RETURNPKT)\n \
MLNewPacket(link);\n read_contents_of_ReturnPacket();"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["That little piece of code is responsible for more ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" programming headaches than anything else! That's because it appears \
throughout the sample programs, so people copy it verbatim into their own \
programs without really being aware of its consequences. Specifically, they \
use it in situations where a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" will not be coming. What happens then? Well, you drain off all packets \
waiting for a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", then call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", which will block forever, so your program hangs.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Therefore, it is extremely important to be sure that you actually will be \
getting a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" before you use this code fragment! Typically, people encounter this error \
for one of two reasons: they get out of sync with the incoming packets, so \
that they have already discarded the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" by the time the loop is entered; or, they send computations to the kernel \
wrapped in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" (or, equivalently, they wrap it in the function ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Enter",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox["), which causes results to come back in a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", not a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
". The latter issue is discussed in Section 2.3; for now I'll assume you \
are sending an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" (if you will be getting a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", just substitute that for ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" in this discussion).",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"If your program is hanging unexpectedly, it is almost a certain bet that \
it is hanging in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" because you are looping waiting for a packet type that will never \
arrive.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Another potential problem is that you have done something to cause a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" error before the loop is entered. In that case, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" (like most ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" functions) will return 0 until the error condition is cleared with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLClearError",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". A simple way to avoid this problem is to use the following \
packet-reading loop instead:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" while ((pkt = MLNextPacket(link)) && pkt != RETURNPKT)\n \
MLNewPacket(link);\n if(!pkt) {\n handle_error(link); /* \
including calling MLClearError(link) */\n } else {\n \
read_contents_of_ReturnPacket();\n }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Finally, it is often the case that you don't even care what is in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". For example, if you send a definition to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" like ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["f[x_] := x^2",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", then you will get back a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" that contains the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Null",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" (many users are not aware that an expression of this type returns \
something, because there is no ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Out",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" line printed). Another example is if you read in a package with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox["--the return value of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" is the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Null",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". If you don't want to read the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", throw it away with a final call to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNewPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[":",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(link, \"Get\", 1);\n MLPutString(link, \
\"Statistics`NonlinearFit`\");\n\n while ((pkt = MLNextPacket(link)) && \
pkt != RETURNPKT)\n MLNewPacket(link);\n MLNewPacket(link); \
/* abandon the RETURNPKT */"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The second most common ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" error is to forget to drain off the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
"s from code that you send, especially \"initialization\" code you send \
before your real work begins. If you forget to run the \"throw away \
everything up to and including the next ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox["\" loop, then later when you read a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" that you expect to have the result of the first \"real\" computation, you \
will instead be getting a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" from something sent earlier. Remember that everything you send will cause \
a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" to be sent back, even if just contains the symbol ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Null",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData[{
StyleBox["2.4.2 Packets ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" Might Send to You",
Evaluatable->False,
AspectRatioFixed->True]
}], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["There are quite a few packet types that ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" might send to your program. Generally, if you are not allowing a user to \
directly interact with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" (so you as the programmer have control over what gets sent), you don't \
need to worry about many of them. You either won't get them, or you can just \
discard them because you are not interested in their contents. For some of \
them (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["e.g.",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InputNamePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["OutputNamePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
"), whether or not you get them depends on how you send the input to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" in the first place (see Section 2.3). Here is a brief discussion of the \
more important types. Again, I refer you to the frontend.c program for an \
example of how to handle every one of the packet types you might get from ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["InputNamePacket, OutputNamePacket"], "Subsubsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["You will get these any time you send something wrapped in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" or ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" (you may not always get an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["OutputNamePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", as discussed earlier). Their contents are strings, something like ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["\"In[1]:=\"",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" or ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["\"Out[12]=\"",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", which you can print directly to the screen if you want to show the \
prompts. If you don't want to show these to the user, you probably should use \
",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EvaluatePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" to send the original input, as explained in Section 2.3, so they won't \
even be generated.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData[
"ReturnPacket, ReturnTextPacket, ReturnExpressionPacket"], "Subsubsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["These packets will contain the result of an evaluation. A ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" will contain a formatted string, ready to be printed directly to the \
screen (that is, it will have the appropriate line-breaking and padding so \
that exponents and fractions will be lined up). A ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" results from sending an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["EnterTextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[". In contrast, a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" or a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnExpressionPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" will contain an expression, which you will have to read with an \
appropriate series of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" calls. This is discussed in more detail below.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["MessagePacket"], "Subsubsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"This packet signals the beginning of a warning or error message generated by \
the kernel. An example is the following:"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"Part::partd: Part specification x[[1]] is longer than depth of object."],
"Message",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["A ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MessagePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" will contain two things: first, a symbol (to be read with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetSymbol",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[") that is the name of the function (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Part",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" in the above example), then a string that is the \"tag\" of the message (\
\"partd\" above). The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MessagePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" will be followed by a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["TextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" that contains the text of the message.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["TextPacket"], "Subsubsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["This is used for the output of a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Print",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" statement, the output of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["?Function",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" or ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Information[Function]",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[", and also the text of a message (see discussion of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MessagePacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox["). The contents will always be a string (to be read with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetString",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", of course).",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["DisplayPacket"], "Subsubsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"This will hold PostScript code for a graphic, in the form of a string. \
There may be a series of these, each containing a piece of the total \
PostScript. A ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["DisplayEndPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" will signal the last piece of PostScript. How to handle graphics is \
discussed elsewhere in this tutorial.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.4.3 Reading the Contents of a Packet"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Once you have \"opened\" a packet with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" and you have decided not to discard it, you need to read out the \
contents. This will require some appropriate sequence of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" calls. In many cases, the contents of the packet are something simple, \
like a string, which can be read with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetString",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". In the case of a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
", though, the contents are an expression, and you may need to implement \
some expression-reading logic of your own. An example of this is the function \
",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["read_and_print_expression",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" from the factorinteger.c example program that is included with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". The basic idea is to recursively descend into the expression, calling ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetType",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" for each new element to find out what ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" call you will need to read it properly.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"If you find yourself embarking on such a project, ask yourself if it is \
really necessary for you to receive the results as an arbitrary expression. \
If you are expecting some simple type of expression, like a number, that is \
meaningful in a C program, then fine. But for many applications, there isn't \
really a whole lot to do with the dismembered expression pieces you're going \
to get from the process. Often, what people really want is just a string form \
of the result, because they are only going to display it on the screen. If \
that's the case, send the computation in such a way that you will get back a \
formatted string as a result (see Section 2.3)."], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.4.4 The \"Disown\" Functions"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" has several functions with \"",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Disown",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["\" in their name, for example ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDisownString",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDisownIntegerList",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". Whenever you use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" to receive an object whose size cannot be known at compile time (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["e.g.",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", a string, symbol, list, or array), ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" reads the object into its own memory space and gives you only the address \
of the data. For example, in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGetString",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[", you pass the address of a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["char*",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" (i.e., a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["char**",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["), and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" stuffs the address of the string it received into your ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["char*",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". You don't have to allocate any memory yourself or worry about how big \
the data is. At this point, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" \"owns\" the data, and it is waiting for your permission to free the \
memory that it occupies, which you grant when you call the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDisown",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" functions. Between the time you call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLDisown",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", you can only read the data--do not try to modify it in place. If you \
need to do that, allocate your own memory and copy the data into it (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["e.g.",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", using ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["strcpy",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[").",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.5 Blocking, Yield Functions, and All That"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["When you issue a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["-type call (including ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox["), ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" will block if there is nothing waiting to be read from the link. This \
will cause a problem if you need to do something (like service your user \
interface) without interruption. There are three solutions for handling this \
problem.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["2.5.1 MLReady and MLFlush"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["MLReady",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" returns 0 to indicate that there is no data on the link waiting to be \
read, and 1 to indicate there is. In other words, it tells you whether a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
"-type call will block. You can use it to check that there is data waiting \
before you call a reading function.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLFlush(lp);\n if(MLReady(lp)) {\n MLNextPacket(lp);\n \
...handle the packet...\n }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Note the call to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLFlush",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" before ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLReady",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" is buffered, meaning that if you call a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Put",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" function, the data is not necessarily sent right away, but might be held \
in a buffer instead. Any time you need to ensure that the data is sent \
immediately, you can call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLFlush",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". An example when you might need to do this is if you are sending \
something to the kernel that will trigger a side effect, like writing \
something to a file that your program will read right away.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["In the normal flow of writing and reading the link, calls to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLFlush",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" are generally unnecessary, since ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" automatically flushes the link at appropriate times. Specifically, if you \
issue a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
"-type call and there is nothing there, your side of the link will be \
flushed. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLReady",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", however, does not flush the link, so it can lie to you in that it is \
possible for ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLReady",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" to return 0, yet a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" call would not block. This will happen if your side has some data that \
when sent will trigger the other side to reply--the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" flushes the link and receives the reply right away. For this reason, you \
should always call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLFlush",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" before ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLReady",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.5.2 Let It Block"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["When ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" is blocking, it calls what is known as a yield function. A yield function \
must have two features: (1) it allows other processes to get processor time \
(on operating systems like Macintosh and Windows that do not have preemptive \
multitasking); (2) it returns 0 or 1 to indicate whether ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" should continue blocking or bail out of the read call.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["There is a default yield function inside ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", the details of which differ from platform to platform. For example, on \
the Macintosh, it calls ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["WaitNextEvent",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" to allow other processes to get time. If it didn't yield to other \
processes, then the sending side would never get a chance to send anything \
and your read call would block forever!",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"You can install your own yield function if you wish, and this provides a \
solution to the blocking problem. You simply call back to your main event \
loop from inside your yield function. When the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" call returns, you process the result, send something else if you want, \
and then immediately issue another ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Get",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" call. Your program can spend most of its life blocking inside a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" function, calling the main event loop to run the user interface or other \
periodic tasks. Here is a trivial skeleton of what such a yield function \
might look like. Note that the second argument to a yield function is of type \
",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLYieldParameters",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[". This is a reserved argument that is currently used only in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
"'s own default yield function. You should simply ignore this argument.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" int yield_function(MLINK link, MLYieldParameters yp) {\n \
one_pass_main_event_loop();\n return 0; /* keep on blocking */\n \
}"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The function you use to install your own yield function is ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLSetYieldFunction",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
". The interface to this function has changed a bit to support some new ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" platforms (Windows and Power Macintosh). To see how to call it, I \
recommend that you look at a .tm.c file generated by mprep (see the first \
chapter for details). The code generated by mprep installs its own yield \
function that works in just the way I've described above (template programs \
spend their lives blocking inside ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLNextPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", waiting for the kernel to call them). This will show you the proper way \
to call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLSetYieldFunction",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" for your platform and version of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Having said this, note that in Versions 2.2.x and earlier of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" on Unix, there is a bug that prevents ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" from calling your yield function when it is blocking in an ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MLGet",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
"-type call, unless your program receives a Unix signal. Thus, you will \
need to set some sort of timer to periodically send yourself a signal, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["SIGALRM",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" for example.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["One final note: ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" is not fully reentrant, in the sense that you cannot issue a call on a \
link while another call on that link is in progress (you ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["can",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" read or write to different links). Therefore, if you allow your user \
interface to run while inside the yield function, you must prevent users from \
doing anything that would trigger a call on the same link. Thus, before \
calling the main event loop, you might need to disable some menu choices or \
other features. You can then re-enable them before returning from the yield \
function.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.5.3 Write a Multithreaded Program"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"If your operating system and development environment allow you to write \
multithreaded programs, this is an ideal solution to the blocking problem. \
Most operating systems support multithreaded programming, including \
Macintosh, Windows NT, the upcoming Windows 4.0, and many flavors of Unix. \
Simply fork a thread in which the read occurs and let it block. You carry on \
other processing in other threads."], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.6 Graphics"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["When many people think of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" graphics, they think of the PostScript code that is rendered into the \
image they see. It is important to remember that a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" graphic is an expression, like everything else in ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". It might look something like:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"Graphics[{Line[{{0,0}, {1,1}}], Point[{.5,.5}], .... ]"], "Input",
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The PostScript code is generated as a side-effect of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Display",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" function, and is not an inherent part of the graphics object.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"If you send a command that produces a graphic, say for example:"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(lp, \"ToExpression\", 1);\n MLPutString(lp, \
\"Plot[x^2, {x,0,1}]\");"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["You will get back a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["ReturnPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" containing the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Graphics",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" object, and also a series of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["DisplayPackets",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" containing PostScript (the last one of which is a ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["DisplayEndPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
"). If you want to display the graphic you have two choices: either render \
the PostScript somehow, or convert the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Graphics",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[
" object into a form that you can render. This may seem obvious, but many \
programmers forget that handling the PostScript is not their only option.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"It is likely that in the future the PostScipt interpreter that is built \
into the notebook front end will be spun off as a separate ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" program that is callable by programmers. When this happens, it will be \
easy for ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" programmers to render ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" PostScript in their own programs. Until then, though, dealing with \
PostScript is problematic unless your machine or environment supports \
PostScript rendering.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["You might want to consider dealing directly with the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" graphics expression instead of the PostScript. If you have a graphics \
library among your programming tools, you will probably find it is not \
difficult to convert most ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" graphics into the native functions of your library. ",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"Here are some tips for handling PostScript on various platforms."], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["2.6.1 Unix"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"Under Unix, standalone PostScript interpreters have always been part of \
the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" distribution. You can use them in the same way as they are used by the \
non-notebook interface. What you will get is a separate window, not a part of \
your program, managed by the PostScript interpreter (",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["e.g.",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", motifps, olps, etc.) To enable this behavior, read in the appropriate \
graphics initialization file. On most Unix systems, this will be Motif.m:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" MLPutFunction(link, \"EvaluatePacket\", 1);\n \
MLPutFunction(link, \"Get\", 1);\n MLPutString(link, \"Motif.m\"); \
/* NeXT.m on a NeXT */\n MLEndPacket(link);\n \n /* Now, read \
and discard packets up to, and including, the next\n ReturnPacket, \
which will be the return value of the \"Get\" function.\n It will \
contain the symbol Null, which is of no interest. */"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"This imitates what happens when the kernel is run from the Unix command \
line. When you issue commands that trigger graphics, you will not get ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["DisplayPacket",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
"s containing PostScript; rather, a window displaying the graphic will \
appear.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["2.6.2 Macintosh and Windows"], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["There is currently no supported way to render ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" PostScript on these platforms. For Windows, see the source for the demo \
Visual Basic front end, which performs this feat.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"It is possible to have your program create a skeleton notebook file and \
write the PostScript to that file. When the file is opened in the notebook \
front end, the graphics will be displayed. The frontend.c program \
demonstrates this."], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]]}, Open]]}, Open]],
Cell[CellGroupData[{Cell[TextData["3. Using Other Languages"], "Subsubtitle",
Evaluatable->False,
PageBreakAbove->True,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData["3.1 C++"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" library can be called directly from C++ exactly as it is called from C. \
You don't even need to think about it. However, there is a complication when \
writing installable functions, depending on what version of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" you have. The issue is that in some versions of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" the C code that is generated by mprep is K&R-style (for compatibility \
with older C compilers), not ANSI-style, and so it will not pass through a \
C++ compiler. Beginning with Version 2.2.3, mprep has the ability to generate \
.tm.c files that are legal C++ files (you can rename them .tm.cpp if you \
wish). On Macintosh and Windows, this is the default behavior. On Unix \
platforms, you need to specify a command-line argument to mprep to have it \
generate C++-compatible code. This behavior is undocumented and may change in \
the future, but for now the argument is -prototypes:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" /math/Bin/MathLink/mprep -prototypes addtwo.tm -o addtwo.tm.c"],
"Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"If you have Version 2.2.2 or earlier, you must use a C compiler on the \
.tm.c file generated by mprep. You can still code your external functions in \
C++ and pass those source files through your C++ compiler. However, note that \
your functions are being called from the .tm.c file, and thus from C. C++ \
provides a mechanism whereby you can inform the compiler that certain \
functions will be called from C: the",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox[" extern \"C\"",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" declaration. This tells the C++ compiler not to perform the usual \
name-mangling.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"In summary, if you are not making use of the template mechanism (that is, \
you will not have a .tm file in your project), you can call ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" from C++ without worrying about language issues. If you are using a .tm \
file, and have Version 2.2.2 or later of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" materials, you also don't need to worry about these issues since you can \
rename the .tm.c file .tm.cpp and pass it through the C++ compiler. On Unix, \
you will need to specify the -proto option to mprep to enable this. If you \
have an earlier version of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", you will need to obey these two guidelines:\n -- The .tm.c file \
must be compiled with a C compiler.\n -- Every C++ function named in the \
.tm file (and which will therefore be called\n from C) needs to be \
declared ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["extern \"C\"",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True,
FontSize->9]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData["3.2 FORTRAN and Others"], "Section",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" library is written in C. To create programs that use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", you need to call the functions in this library. For this reason, and \
others outlined below, ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" is easiest to use from C. You can, however, use ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" in conjunction with FORTRAN or other languages. This section refers \
specifically to FORTRAN, but much of the information is relevant to other \
languages as well.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["As discussed earlier, there are two broad classes of uses of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
". The first and most common class of uses is to make external functions, \
written in some compiled language like C or FORTRAN, available within ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" as if they were built-in functions. We call such external functions \
\"installable\" since they use the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Install",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10,
FontWeight->"Bold"],
StyleBox[" mechanism to be made available within ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", or alternatively \"template-based\" since they involve writing a \
template file. The second class of uses of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" is to allow your own programs to make use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" as a computational engine. It is your program that users interact with, \
and the services of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" are used in the background. These two uses of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" present different issues and problems to the FORTRAN programmer, so they \
will be discussed separately.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[CellGroupData[{Cell[TextData[{
StyleBox["3.2.1 Calling External FORTRAN Functions from ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"]
}], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"The mprep program writes C code for a very significant amount of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
"-related portions (perhaps all of it) of an installable program. It is \
convenient to make use of this template mechanism when you want to call \
external functions from ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", no matter what language they are written in. This requires that you have \
a C compiler. You may not need to know C in any significant sense, because \
the C code that you write may only be a few lines, and some of that is \
\"boilerplate\" code that is the same for every program and can just be \
copied out of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink Reference Guide",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" or the sample programs supplied with ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[".",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"You will be creating a C program that needs to call your external FORTRAN \
function. The exact details of how you prepare your FORTRAN routine to be \
called from C depends on details of your FORTRAN compiler, and perhaps also \
your C compiler. The difficulty of doing this depends on the types of \
parameters you need to pass from C to FORTRAN and back. If you only need to \
pass integers or real numbers, then it may be very simple. It is more \
complicated to work with strings and arrays, since their representations \
differ in the two languages. As a simple example, consider how you would \
modify the basic addtwo example. Everything about this example remains the \
same except the actual C code for the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" function, and the fact that there is now a separately compiled FORTRAN \
file containing code for the computation. Here's how the FORTRAN code might \
look:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" subroutine addtwoF(i, j, k)\n integer*4 i,j,k\n k = i + j\n \
return\n end"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["Here's how the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function might look:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" int addtwo(int i, int j) {\n \n int result;\n\n \
addtwoF(&i, &j, &result);\n return result;\n }"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" C code is just a \"wrapper\" that prepares things for calling the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwoF",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" function. The & is the \"address-of\" operator in C, and it is needed \
because FORTRAN expects arguments to be passed by reference, not by value (as \
is the case with C). Thus, you need to pass to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwoF",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" not the values of the integers ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["i",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" and ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["j",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
", but the actual addresses where the values are stored. The FORTRAN code \
extracts the values from these addresses, adds them, then stuffs the result \
at the address of the result variable. On some systems, you may need to put \
an underscore at the end of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwoF",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function in the C source, calling it as ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwoF_(&i, &j, &result)",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[";",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"It is also possible that your FORTRAN compiler allows you to specify that \
parameters to a function will be passed by value. If this is the case, then \
you may be able to completely dispense with the C portion of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" function because your FORTRAN code will be written in a way that it can \
be called exactly as if it were written in C. The call to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" is made from the code that mprep creates, and of course it writes the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" function call as if ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" were written in C. If your FORTRAN compiler lets you write FORTRAN that \
adheres to C's calling conventions, then you may not need to write any C \
wrappers around your functions. An example is Absoft FORTRAN, which includes \
the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["VALUE",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[
" keyword to specify that parameters will be passed by value. Here is what \
the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" code might look like in such a dialect of FORTRAN:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
" integer*4 function addtwo(i, j)\n integer*4 i,j\n VALUE i, j\n \
addtwo = i + j\n return\n end"], "Special1",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["In this case, there is no ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["addtwo",
Evaluatable->False,
AspectRatioFixed->True,
FontFamily->"Courier",
FontSize->10],
StyleBox[" written in C.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"I want to emphasize that different FORTRAN compilers may use different \
calling conventions, and thus there are many issues that might need to be \
resolved. These include what order the arguments are passed in, whether they \
are on the stack or in registers, whether the return value is on the stack or \
in a register, etc."], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"Whichever of these two methods you choose, remember that you need a C \
compiler, and that the issue is not how to call C from FORTRAN, but rather \
how to call FORTRAN from C. You should consult your FORTRAN compiler's \
documentation for information on how to write and compile FORTRAN functions \
so that they can be called from C."], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData[{
StyleBox["3.2.2 ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InterCall ",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox["TM",
Evaluatable->False,
AspectRatioFixed->True,
FontSize->10,
FontVariations->{"CompatibilityType"->"Superscript"}]
}], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"There is a commercial product (not from Wolfram Research) called ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InterCall",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" that simplifies the process of calling external FORTRAN (or C) functions \
from within ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". This method uses ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" only indirectly. ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InterCall",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" has many capabilities, and I make no attempt to describe them here. This \
discussion is not an endorsement of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InterCall",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". For more information, consult ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathSource",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[", which has a lot of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InterCall",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
"-related materials. Try sending the following email message to \
mathsource@wri.com:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[" find InterCall"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"You will get a return mailing of abstracts of items on MathSource \
pertaining to ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["InterCall",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[". Probably the most useful item is this one:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"0202-587: InterCall(tm) Information Sheet and Abridged Manual (June 1992)\n \
Author: Terry Robb\n InterCall completely integrates the symbolic \
capabilities of\n Mathematica with the numeric routines of any external \
library. You\n can pass a Mathematica function, array, or any other \
expression as\n an argument to any external routine and InterCall will \
send the\n correct type of information to that external routine.\n\n \
0011: Info.txt Plain-text information sheet (5 kilobytes)\n\n 0022: \
InterCall.tex TeX version of Abridged InterCall Manual (53\n \
kilobytes)\n\n 0033: InterCall.ps PostScript version of Abridged \
InterCall\n Manual (180 kilobytes)"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[
"If you want, say, the Info.txt document, send the following message to \
mathsource@wri.com:"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[" send 0202-587-0011"], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]],
Cell[CellGroupData[{Cell[TextData[{
StyleBox["3.2.3 Calling ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" from a FORTRAN Program",
Evaluatable->False,
AspectRatioFixed->True]
}], "Subsection",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox["The other class of uses of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" is where you write the program that the user interacts with, and use the \
services of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["Mathematica",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" in the background. This requires more in-depth use of the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" library, because you will be writing all the code yourself (opening and \
closing the link, putting and getting all expressions, checking for and \
handling errors, etc.) If you need to make extensive use of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" in such a program, it may be easiest to write in C (or at least write the \
",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
"-related portions of your program in C). However, since many FORTRAN \
compilers allow you to call external functions written in C, it is possible \
to make ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" calls directly from a FORTRAN program. Unfortunately, there are \
differences in calling conventions and data representations that need to be \
overcome.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"One approach is to write some \"glue\" code that acts as a wrapper around \
the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" functions and serves to translate back and forth between FORTRAN and C \
conventions. (That's what was done in the first example above, although it \
was done in reverse--the glue was so that FORTRAN could be called from C.) I \
suppose it would be possible to write the glue code in FORTRAN, depending on \
the capabilities of your FORTRAN compiler, but it would be easiest to write \
in C. Either way, if you know enough about C to write this glue, then you'll \
probably want to just do the whole project in C. Fortunately, someone else \
has already written a basic glue library, and it is available on ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathSource",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
", although it has not been updated for a while. I have not used it myself, \
but I have no reason to believe that it doesn't still work. To get it, send a \
message with the following body to mathsource@wri.com:",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[" send 0205-434"], "Text",
Evaluatable->False,
AspectRatioFixed->True],
Cell[TextData[{
StyleBox[
"This package provides a C source file that encapsulates a basic set of ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[
" calls in such a way that they can be called from FORTRAN. You compile the \
file (with a C compiler, of course) to create an external library that \
provides a number of functions that you can call from FORTRAN, instead of \
directly using the functions in the ",
Evaluatable->False,
AspectRatioFixed->True],
StyleBox["MathLink",
Evaluatable->False,
AspectRatioFixed->True,
FontSlant->"Italic"],
StyleBox[" library itself.",
Evaluatable->False,
AspectRatioFixed->True]
}], "Text",
Evaluatable->False,
AspectRatioFixed->True]}, Open]]}, Open]]}, Open]]}, Open]]
},
FrontEndVersion->"Macintosh 3.0",
ScreenRectangle->{{0, 640}, {0, 460}},
WindowToolbars->{},
CellGrouping->Manual,
WindowSize->{520, 365},
WindowMargins->{{28, Automatic}, {Automatic, 16}},
PrivateNotebookOptions->{"ColorPalette"->{RGBColor, -1}},
ShowCellLabel->True,
ShowCellTags->False,
RenderingOptions->{"ObjectDithering"->True,
"RasterDithering"->False},
MacintoshSystemPageSetup->"\<\
AVU/IFiQKFD000000VHFh09V7j0000000OlH809FV"
]
(***********************************************************************
Cached data follows. If you edit this Notebook file directly, not using
Mathematica, you must remove the line containing CacheID at the top of
the file. The cache data will then be recreated when you save this file
from within Mathematica.
***********************************************************************)
(*CellTagsOutline
CellTagsIndex->{}
*)
(*CellTagsIndex
CellTagsIndex->{}
*)
(*NotebookFileOutline
Notebook[{
Cell[CellGroupData[{
Cell[1731, 51, 327, 13, 70, "Title",
Evaluatable->False],
Cell[2061, 66, 109, 2, 70, "Subtitle",
Evaluatable->False],
Cell[2173, 70, 1686, 54, 70, "Text",
Evaluatable->False],
Cell[3862, 126, 1106, 37, 70, "Text",
Evaluatable->False],
Cell[4971, 165, 846, 25, 70, "Text",
Evaluatable->False],
Cell[5820, 192, 1284, 38, 70, "Text",
Evaluatable->False],
Cell[7107, 232, 507, 15, 70, "Text",
Evaluatable->False],
Cell[7617, 249, 160, 4, 70, "Special3",
Evaluatable->False,
PageBreakAbove->True],
Cell[7780, 255, 111, 2, 70, "Special4",
Evaluatable->False],
Cell[7894, 259, 138, 3, 70, "Special4",
Evaluatable->False],
Cell[8035, 264, 121, 2, 70, "Special4",
Evaluatable->False],
Cell[8159, 268, 107, 2, 70, "Special4",
Evaluatable->False],
Cell[8269, 272, 112, 2, 70, "Special4",
Evaluatable->False],
Cell[8384, 276, 119, 2, 70, "Special4",
Evaluatable->False],
Cell[8506, 280, 97, 2, 70, "Special4",
Evaluatable->False],
Cell[8606, 284, 112, 2, 70, "Special4",
Evaluatable->False],
Cell[8721, 288, 97, 2, 70, "Special4",
Evaluatable->False],
Cell[8821, 292, 98, 2, 70, "Special4",
Evaluatable->False],
Cell[8922, 296, 136, 3, 70, "Special3",
Evaluatable->False],
Cell[9061, 301, 99, 2, 70, "Special4",
Evaluatable->False],
Cell[9163, 305, 111, 2, 70, "Special4",
Evaluatable->False],
Cell[9277, 309, 116, 2, 70, "Special4",
Evaluatable->False],
Cell[9396, 313, 120, 2, 70, "Special4",
Evaluatable->False],
Cell[9519, 317, 122, 2, 70, "Special4",
Evaluatable->False],
Cell[9644, 321, 91, 2, 70, "Special4",
Evaluatable->False],
Cell[9738, 325, 103, 2, 70, "Special3",
Evaluatable->False],
Cell[9844, 329, 86, 2, 70, "Special4",
Evaluatable->False],
Cell[9933, 333, 101, 2, 70, "Special4",
Evaluatable->False],
Cell[CellGroupData[{
Cell[10057, 337, 492, 18, 70, "Subsubtitle",
Evaluatable->False,
PageBreakAbove->True],
Cell[10552, 357, 1985, 58, 70, "Text",
Evaluatable->False],
Cell[12540, 417, 972, 28, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[13535, 447, 110, 2, 70, "Section",
Evaluatable->False],
Cell[13648, 451, 542, 17, 70, "Text",
Evaluatable->False],
Cell[14193, 470, 262, 5, 70, "Special1",
Evaluatable->False],
Cell[14458, 477, 1668, 59, 70, "Text",
Evaluatable->False],
Cell[16129, 538, 110, 2, 70, "Text",
Evaluatable->False],
Cell[16242, 542, 298, 6, 70, "Special1",
Evaluatable->False],
Cell[16543, 550, 2638, 91, 70, "Text",
Evaluatable->False],
Cell[19184, 643, 141, 3, 70, "Input"],
Cell[19328, 648, 1034, 39, 70, "Text",
Evaluatable->False],
Cell[20365, 689, 527, 16, 70, "Text",
Evaluatable->False],
Cell[20895, 707, 115, 2, 70, "Special1",
Evaluatable->False],
Cell[21013, 711, 1412, 39, 70, "Text",
Evaluatable->False],
Cell[22428, 752, 358, 6, 70, "Text",
Evaluatable->False],
Cell[22789, 760, 133, 3, 70, "Special1",
Evaluatable->False],
Cell[22925, 765, 304, 6, 70, "Text",
Evaluatable->False],
Cell[23232, 773, 814, 31, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[24069, 806, 79, 1, 70, "Input"],
Cell[24151, 809, 155, 7, 70, "Output",
Evaluatable->False]
}, Open ]],
Cell[24318, 818, 464, 17, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[24805, 837, 71, 1, 70, "Input"],
Cell[24879, 840, 173, 7, 70, "Output",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[25084, 849, 64, 1, 70, "Input"],
Cell[25151, 852, 104, 6, 70, "Output",
Evaluatable->False]
}, Open ]],
Cell[25267, 860, 1642, 57, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[26932, 919, 60, 1, 70, "Input"],
Cell[26995, 922, 196, 4, 70, "Print",
Evaluatable->False]
}, Open ]],
Cell[27203, 928, 996, 30, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[28231, 960, 365, 13, 70, "Section",
Evaluatable->False],
Cell[28599, 975, 1146, 39, 70, "Text",
Evaluatable->False],
Cell[29748, 1016, 701, 23, 70, "Text",
Evaluatable->False],
Cell[30452, 1041, 377, 7, 70, "Special1",
Evaluatable->False],
Cell[30832, 1050, 1796, 63, 70, "Text",
Evaluatable->False],
Cell[32631, 1115, 125, 3, 70, "Input"],
Cell[32759, 1120, 1107, 41, 70, "Text",
Evaluatable->False],
Cell[33869, 1163, 545, 9, 70, "Special1",
Evaluatable->False],
Cell[34417, 1174, 1020, 35, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[35469, 1211, 120, 2, 70, "Section",
Evaluatable->False],
Cell[35592, 1215, 1026, 29, 70, "Text",
Evaluatable->False],
Cell[36621, 1246, 2159, 80, 70, "Text",
Evaluatable->False],
Cell[38783, 1328, 143, 4, 70, "Special1",
Evaluatable->False],
Cell[38929, 1334, 1307, 49, 70, "Text",
Evaluatable->False],
Cell[40239, 1385, 294, 6, 70, "Special1",
Evaluatable->False],
Cell[40536, 1393, 2095, 74, 70, "Text",
Evaluatable->False],
Cell[42634, 1469, 961, 33, 70, "Text",
Evaluatable->False],
Cell[43598, 1504, 119, 2, 70, "Special1",
Evaluatable->False],
Cell[43720, 1508, 1560, 56, 70, "Text",
Evaluatable->False],
Cell[45283, 1566, 129, 3, 70, "Special1",
Evaluatable->False],
Cell[45415, 1571, 1191, 37, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[46638, 1610, 106, 2, 70, "Section",
Evaluatable->False],
Cell[46747, 1614, 1230, 40, 70, "Text",
Evaluatable->False],
Cell[47980, 1656, 282, 5, 70, "Special1",
Evaluatable->False],
Cell[48265, 1663, 1120, 40, 70, "Text",
Evaluatable->False],
Cell[49388, 1705, 355, 6, 70, "Special1",
Evaluatable->False],
Cell[49746, 1713, 1418, 43, 70, "Text",
Evaluatable->False],
Cell[51167, 1758, 157, 4, 70, "Special1",
Evaluatable->False],
Cell[51327, 1764, 614, 18, 70, "Text",
Evaluatable->False],
Cell[51944, 1784, 132, 3, 70, "Special1",
Evaluatable->False],
Cell[52079, 1789, 117, 2, 70, "Text",
Evaluatable->False],
Cell[52199, 1793, 156, 4, 70, "Special1",
Evaluatable->False],
Cell[52358, 1799, 756, 29, 70, "Text",
Evaluatable->False],
Cell[53117, 1830, 1102, 35, 70, "Text",
Evaluatable->False],
Cell[54222, 1867, 609, 10, 70, "Special1",
Evaluatable->False],
Cell[54834, 1879, 2559, 96, 70, "Text",
Evaluatable->False],
Cell[57396, 1977, 630, 22, 70, "Text",
Evaluatable->False],
Cell[58029, 2001, 1178, 18, 70, "Special1",
Evaluatable->False],
Cell[59210, 2021, 3676, 131, 70, "Text",
Evaluatable->False],
Cell[62889, 2154, 940, 32, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[63861, 2188, 111, 2, 70, "Section",
Evaluatable->False],
Cell[63975, 2192, 894, 24, 70, "Text",
Evaluatable->False],
Cell[64872, 2218, 1184, 30, 70, "Text",
Evaluatable->False],
Cell[66059, 2250, 1725, 58, 70, "Text",
Evaluatable->False],
Cell[67787, 2310, 424, 8, 70, "Special1",
Evaluatable->False],
Cell[68214, 2320, 467, 16, 70, "Text",
Evaluatable->False],
Cell[68684, 2338, 626, 18, 70, "Text",
Evaluatable->False],
Cell[69313, 2358, 298, 6, 70, "Special1",
Evaluatable->False],
Cell[69614, 2366, 239, 5, 70, "Text",
Evaluatable->False],
Cell[69856, 2373, 192, 4, 70, "Special1",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[70080, 2379, 118, 2, 70, "Section",
Evaluatable->False],
Cell[70201, 2383, 2194, 74, 70, "Text",
Evaluatable->False],
Cell[72398, 2459, 1359, 47, 70, "Text",
Evaluatable->False],
Cell[73760, 2508, 847, 31, 70, "Text",
Evaluatable->False],
Cell[74610, 2541, 156, 4, 70, "Special1",
Evaluatable->False],
Cell[74769, 2547, 364, 14, 70, "Text",
Evaluatable->False],
Cell[75136, 2563, 579, 9, 70, "Special1",
Evaluatable->False],
Cell[75718, 2574, 2966, 107, 70, "Text",
Evaluatable->False],
Cell[78687, 2683, 279, 5, 70, "Special1",
Evaluatable->False],
Cell[78969, 2690, 780, 29, 70, "Text",
Evaluatable->False],
Cell[79752, 2721, 1593, 56, 70, "Text",
Evaluatable->False],
Cell[81348, 2779, 1302, 45, 70, "Text",
Evaluatable->False],
Cell[82653, 2826, 1856, 63, 70, "Text",
Evaluatable->False],
Cell[84512, 2891, 296, 6, 70, "Special1",
Evaluatable->False],
Cell[84811, 2899, 409, 15, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[85252, 2916, 96, 2, 70, "Section",
Evaluatable->False],
Cell[85351, 2920, 1943, 60, 70, "Text",
Evaluatable->False],
Cell[87297, 2982, 1814, 56, 70, "Text",
Evaluatable->False],
Cell[89114, 3040, 593, 9, 70, "Special1",
Evaluatable->False],
Cell[89710, 3051, 1316, 42, 70, "Text",
Evaluatable->False],
Cell[91029, 3095, 157, 4, 70, "Special1",
Evaluatable->False],
Cell[91189, 3101, 1527, 51, 70, "Text",
Evaluatable->False],
Cell[92719, 3154, 222, 5, 70, "Special1",
Evaluatable->False],
Cell[92944, 3161, 581, 19, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[93548, 3182, 83, 1, 70, "Input"],
Cell[93634, 3185, 131, 3, 70, "Message",
Evaluatable->False],
Cell[93768, 3190, 116, 6, 70, "Output",
Evaluatable->False]
}, Open ]],
Cell[93896, 3198, 894, 33, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[94813, 3233, 74, 1, 70, "Input"],
Cell[94890, 3236, 190, 4, 70, "Message",
Evaluatable->False],
Cell[95083, 3242, 116, 6, 70, "Output",
Evaluatable->False]
}, Open ]]
}, Open ]],
Cell[CellGroupData[{
Cell[95240, 3250, 111, 2, 70, "Section",
Evaluatable->False],
Cell[95354, 3254, 424, 15, 70, "Text",
Evaluatable->False],
Cell[95781, 3271, 120, 2, 70, "Message",
Evaluatable->False],
Cell[95904, 3275, 162, 4, 70, "Message",
Evaluatable->False],
Cell[96069, 3281, 2300, 70, 70, "Text",
Evaluatable->False],
Cell[98372, 3353, 642, 18, 70, "Text",
Evaluatable->False],
Cell[99017, 3373, 166, 4, 70, "Message",
Evaluatable->False],
Cell[99186, 3379, 1512, 53, 70, "Text",
Evaluatable->False],
Cell[100701, 3434, 1929, 54, 70, "Text",
Evaluatable->False],
Cell[102633, 3490, 96, 1, 70, "Input"],
Cell[102732, 3493, 1372, 46, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[104136, 3541, 96, 2, 70, "Section",
Evaluatable->False],
Cell[104235, 3545, 791, 20, 70, "Text",
Evaluatable->False],
Cell[105029, 3567, 1370, 42, 70, "Text",
Evaluatable->False],
Cell[106402, 3611, 1062, 30, 70, "Text",
Evaluatable->False],
Cell[107467, 3643, 2822, 91, 70, "Text",
Evaluatable->False],
Cell[110292, 3736, 453, 8, 70, "Text",
Evaluatable->False],
Cell[110748, 3746, 1431, 44, 70, "Special1",
Evaluatable->False],
Cell[112182, 3792, 606, 17, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[112820, 3811, 97, 2, 70, "Section",
Evaluatable->False],
Cell[CellGroupData[{
Cell[112940, 3815, 131, 3, 70, "Subsection",
Evaluatable->False],
Cell[113074, 3820, 766, 21, 70, "Text",
Evaluatable->False],
Cell[113843, 3843, 807, 20, 70, "Text",
Evaluatable->False],
Cell[114653, 3865, 3268, 105, 70, "Text",
Evaluatable->False],
Cell[117924, 3972, 140, 3, 70, "Input"],
Cell[118067, 3977, 366, 13, 70, "Text",
Evaluatable->False],
Cell[118436, 3992, 878, 13, 70, "Special1",
Evaluatable->False],
Cell[119317, 4007, 192, 4, 70, "Text",
Evaluatable->False],
Cell[119512, 4013, 1597, 56, 70, "Text",
Evaluatable->False],
Cell[121112, 4071, 1353, 39, 70, "Text",
Evaluatable->False],
Cell[122468, 4112, 672, 18, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[123172, 4132, 102, 2, 70, "Subsection",
Evaluatable->False],
Cell[123277, 4136, 957, 31, 70, "Text",
Evaluatable->False],
Cell[124237, 4169, 651, 18, 70, "Text",
Evaluatable->False],
Cell[124891, 4189, 1550, 46, 70, "Text",
Evaluatable->False],
Cell[126444, 4237, 951, 24, 70, "Text",
Evaluatable->False],
Cell[127398, 4263, 524, 16, 70, "Text",
Evaluatable->False],
Cell[127925, 4281, 793, 13, 70, "Special1",
Evaluatable->False],
Cell[128721, 4296, 904, 27, 70, "Text",
Evaluatable->False],
Cell[129628, 4325, 1413, 45, 70, "Text",
Evaluatable->False],
Cell[131044, 4372, 1547, 50, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[132623, 4424, 118, 2, 70, "Subsection",
Evaluatable->False],
Cell[132744, 4428, 369, 6, 70, "Text",
Evaluatable->False],
Cell[133116, 4436, 2005, 65, 70, "Text",
Evaluatable->False],
Cell[135124, 4503, 1055, 30, 70, "Text",
Evaluatable->False],
Cell[136182, 4535, 1915, 65, 70, "Text",
Evaluatable->False],
Cell[138100, 4602, 3030, 106, 70, "Text",
Evaluatable->False],
Cell[141133, 4710, 2377, 81, 70, "Text",
Evaluatable->False],
Cell[143513, 4793, 660, 23, 70, "Text",
Evaluatable->False],
Cell[144176, 4818, 1824, 51, 70, "Text",
Evaluatable->False],
Cell[146003, 4871, 1619, 53, 70, "Text",
Evaluatable->False],
Cell[147625, 4926, 770, 26, 70, "Text",
Evaluatable->False],
Cell[148398, 4954, 623, 10, 70, "Special1",
Evaluatable->False],
Cell[149024, 4966, 1823, 64, 70, "Text",
Evaluatable->False],
Cell[150850, 5032, 2752, 95, 70, "Text",
Evaluatable->False]
}, Open ]]
}, Open ]]
}, Open ]],
Cell[CellGroupData[{
Cell[153652, 5129, 492, 18, 70, "Subsubtitle",
Evaluatable->False,
PageBreakAbove->True],
Cell[154147, 5149, 2243, 75, 70, "Text",
Evaluatable->False],
Cell[156393, 5226, 687, 24, 70, "Text",
Evaluatable->False],
Cell[157083, 5252, 682, 10, 70, "Text",
Evaluatable->False],
Cell[157768, 5264, 1367, 37, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[159158, 5303, 98, 2, 70, "Section",
Evaluatable->False],
Cell[159259, 5307, 391, 7, 70, "Text",
Evaluatable->False],
Cell[159653, 5316, 1064, 16, 70, "Special1",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[160749, 5334, 110, 2, 70, "Section",
Evaluatable->False],
Cell[CellGroupData[{
Cell[160882, 5338, 93, 2, 70, "Subsection",
Evaluatable->False],
Cell[160978, 5342, 3223, 112, 70, "Text",
Evaluatable->False],
Cell[164204, 5456, 134, 3, 70, "Special1",
Evaluatable->False],
Cell[164341, 5461, 787, 26, 70, "Text",
Evaluatable->False],
Cell[165131, 5489, 285, 5, 70, "Special1",
Evaluatable->False],
Cell[165419, 5496, 460, 8, 70, "Text",
Evaluatable->False],
Cell[165882, 5506, 207, 4, 70, "Text",
Evaluatable->False],
Cell[166092, 5512, 322, 6, 70, "Special1",
Evaluatable->False],
Cell[166417, 5520, 622, 18, 70, "Text",
Evaluatable->False],
Cell[167042, 5540, 310, 6, 70, "Text",
Evaluatable->False],
Cell[167355, 5548, 303, 6, 70, "Special1",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[167690, 5556, 96, 2, 70, "Subsection",
Evaluatable->False],
Cell[167789, 5560, 1681, 59, 70, "Text",
Evaluatable->False],
Cell[169473, 5621, 1901, 62, 70, "Text",
Evaluatable->False],
Cell[171377, 5685, 3493, 121, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[174902, 5808, 121, 2, 70, "Subsection",
Evaluatable->False],
Cell[175026, 5812, 1114, 29, 70, "Text",
Evaluatable->False],
Cell[176143, 5843, 257, 5, 70, "Special1",
Evaluatable->False],
Cell[176403, 5850, 382, 13, 70, "Text",
Evaluatable->False],
Cell[176788, 5865, 92, 1, 70, "Input"],
Cell[176883, 5868, 751, 20, 70, "Text",
Evaluatable->False],
Cell[177637, 5890, 172, 3, 70, "Input"],
Cell[177812, 5895, 146, 4, 70, "Text",
Evaluatable->False],
Cell[177961, 5901, 1407, 41, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[179400, 5944, 118, 2, 70, "Subsection",
Evaluatable->False],
Cell[179521, 5948, 3071, 105, 70, "Text",
Evaluatable->False],
Cell[182595, 6055, 918, 32, 70, "Text",
Evaluatable->False],
Cell[183516, 6089, 869, 30, 70, "Text",
Evaluatable->False],
Cell[184388, 6121, 321, 6, 70, "Special1",
Evaluatable->False]
}, Open ]]
}, Open ]],
Cell[CellGroupData[{
Cell[184750, 6129, 115, 2, 70, "Section",
Evaluatable->False],
Cell[184868, 6133, 5043, 184, 70, "Text",
Evaluatable->False],
Cell[189914, 6319, 347, 6, 70, "Special1",
Evaluatable->False],
Cell[190264, 6327, 1346, 46, 70, "Text",
Evaluatable->False],
Cell[191613, 6375, 1573, 46, 70, "Text",
Evaluatable->False],
Cell[193189, 6423, 68, 1, 70, "Input"],
Cell[193260, 6426, 444, 17, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[193727, 6445, 289, 10, 70, "Subsection",
Evaluatable->False],
Cell[194019, 6457, 214, 4, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[194256, 6463, 341, 13, 70, "Subsubsection",
Evaluatable->False],
Cell[194600, 6478, 2502, 88, 70, "Text",
Evaluatable->False],
Cell[197105, 6568, 1645, 51, 70, "Text",
Evaluatable->False],
Cell[198753, 6621, 897, 28, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[199682, 6651, 97, 2, 70, "Subsubsection",
Evaluatable->False],
Cell[199782, 6655, 921, 33, 70, "Text",
Evaluatable->False],
Cell[200706, 6690, 378, 15, 70, "Text",
Evaluatable->False],
Cell[201087, 6707, 264, 5, 70, "Special1",
Evaluatable->False],
Cell[201354, 6714, 1479, 51, 70, "Text",
Evaluatable->False],
Cell[202836, 6767, 732, 25, 70, "Text",
Evaluatable->False],
Cell[203571, 6794, 246, 5, 70, "Special1",
Evaluatable->False],
Cell[203820, 6801, 874, 27, 70, "Text",
Evaluatable->False],
Cell[204697, 6830, 1214, 39, 70, "Text",
Evaluatable->False],
Cell[205914, 6871, 1031, 29, 70, "Text",
Evaluatable->False],
Cell[206948, 6902, 91, 1, 70, "Input"],
Cell[207042, 6905, 178, 4, 70, "Text",
Evaluatable->False],
Cell[207223, 6911, 296, 5, 70, "Special1",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[207551, 6918, 98, 2, 70, "Subsubsection",
Evaluatable->False],
Cell[207652, 6922, 4024, 141, 70, "Text",
Evaluatable->False],
Cell[211679, 7065, 193, 4, 70, "Special1",
Evaluatable->False],
Cell[211875, 7071, 209, 4, 70, "Special1",
Evaluatable->False],
Cell[212087, 7077, 621, 24, 70, "Text",
Evaluatable->False],
Cell[212711, 7103, 1973, 63, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[214716, 7168, 104, 2, 70, "Subsubsection",
Evaluatable->False],
Cell[214823, 7172, 1184, 41, 70, "Text",
Evaluatable->False],
Cell[216010, 7215, 267, 5, 70, "Special1",
Evaluatable->False],
Cell[216280, 7222, 1858, 60, 70, "Text",
Evaluatable->False]
}, Open ]]
}, Open ]],
Cell[CellGroupData[{
Cell[218179, 7284, 130, 3, 70, "Subsection",
Evaluatable->False],
Cell[218312, 7289, 1085, 37, 70, "Text",
Evaluatable->False],
Cell[219400, 7328, 152, 4, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[219575, 7334, 154, 4, 70, "Subsubsection",
Evaluatable->False],
Cell[219732, 7340, 1131, 39, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[220895, 7381, 165, 5, 70, "Subsubsection",
Evaluatable->False],
Cell[221063, 7388, 657, 20, 70, "Text",
Evaluatable->False],
Cell[221723, 7410, 272, 5, 70, "Special1",
Evaluatable->False],
Cell[221998, 7417, 752, 27, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[222782, 7446, 170, 5, 70, "Subsubsection",
Evaluatable->False],
Cell[222955, 7453, 433, 15, 70, "Text",
Evaluatable->False],
Cell[223391, 7470, 324, 6, 70, "Special1",
Evaluatable->False],
Cell[223718, 7478, 1251, 44, 70, "Text",
Evaluatable->False],
Cell[224972, 7524, 325, 6, 70, "Special1",
Evaluatable->False]
}, Open ]]
}, Open ]]
}, Open ]],
Cell[CellGroupData[{
Cell[225347, 7532, 119, 2, 70, "Section",
Evaluatable->False],
Cell[CellGroupData[{
Cell[225489, 7536, 133, 3, 70, "Subsection",
Evaluatable->False],
Cell[225625, 7541, 4017, 127, 70, "Text",
Evaluatable->False],
Cell[229645, 7670, 3845, 128, 70, "Text",
Evaluatable->False],
Cell[233493, 7800, 1808, 53, 70, "Text",
Evaluatable->False],
Cell[235304, 7855, 199, 4, 70, "Special1",
Evaluatable->False],
Cell[235506, 7861, 1398, 45, 70, "Text",
Evaluatable->False],
Cell[236907, 7908, 2741, 96, 70, "Text",
Evaluatable->False],
Cell[239651, 8006, 509, 18, 70, "Text",
Evaluatable->False],
Cell[240163, 8026, 1165, 40, 70, "Text",
Evaluatable->False],
Cell[241331, 8068, 343, 6, 70, "Special1",
Evaluatable->False],
Cell[241677, 8076, 2869, 106, 70, "Text",
Evaluatable->False],
Cell[244549, 8184, 333, 6, 70, "Special1",
Evaluatable->False],
Cell[244885, 8192, 2127, 74, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[247044, 8268, 353, 13, 70, "Subsection",
Evaluatable->False],
Cell[247400, 8283, 2124, 69, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[249547, 8354, 116, 2, 70, "Subsubsection",
Evaluatable->False],
Cell[249666, 8358, 1875, 66, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[251573, 8426, 138, 3, 70, "Subsubsection",
Evaluatable->False],
Cell[251714, 8431, 1881, 64, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[253627, 8497, 96, 2, 70, "Subsubsection",
Evaluatable->False],
Cell[253726, 8501, 194, 4, 70, "Text",
Evaluatable->False],
Cell[253923, 8507, 151, 4, 70, "Message",
Evaluatable->False],
Cell[254077, 8513, 1454, 52, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[255563, 8567, 93, 2, 70, "Subsubsection",
Evaluatable->False],
Cell[255659, 8571, 1387, 50, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[257078, 8623, 96, 2, 70, "Subsubsection",
Evaluatable->False],
Cell[257177, 8627, 635, 20, 70, "Text",
Evaluatable->False]
}, Open ]]
}, Open ]],
Cell[CellGroupData[{
Cell[257853, 8649, 119, 2, 70, "Subsection",
Evaluatable->False],
Cell[257975, 8653, 2360, 79, 70, "Text",
Evaluatable->False],
Cell[260338, 8734, 746, 11, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[261116, 8747, 111, 2, 70, "Subsection",
Evaluatable->False],
Cell[261230, 8751, 4187, 150, 70, "Text",
Evaluatable->False]
}, Open ]]
}, Open ]],
Cell[CellGroupData[{
Cell[265458, 8903, 121, 2, 70, "Section",
Evaluatable->False],
Cell[265582, 8907, 968, 33, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[266573, 8942, 106, 2, 70, "Subsection",
Evaluatable->False],
Cell[266682, 8946, 709, 23, 70, "Text",
Evaluatable->False],
Cell[267394, 8971, 194, 4, 70, "Special1",
Evaluatable->False],
Cell[267591, 8977, 1507, 51, 70, "Text",
Evaluatable->False],
Cell[269101, 9030, 2414, 87, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[271547, 9119, 99, 2, 70, "Subsection",
Evaluatable->False],
Cell[271649, 9123, 834, 24, 70, "Text",
Evaluatable->False],
Cell[272486, 9149, 836, 26, 70, "Text",
Evaluatable->False],
Cell[273325, 9177, 1795, 55, 70, "Text",
Evaluatable->False],
Cell[275123, 9234, 232, 5, 70, "Special1",
Evaluatable->False],
Cell[275358, 9241, 1661, 52, 70, "Text",
Evaluatable->False],
Cell[277022, 9295, 1174, 38, 70, "Text",
Evaluatable->False],
Cell[278199, 9335, 1019, 28, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[279250, 9365, 116, 2, 70, "Subsection",
Evaluatable->False],
Cell[279369, 9369, 486, 8, 70, "Text",
Evaluatable->False]
}, Open ]]
}, Open ]],
Cell[CellGroupData[{
Cell[279896, 9379, 90, 2, 70, "Section",
Evaluatable->False],
Cell[279989, 9383, 893, 29, 70, "Text",
Evaluatable->False],
Cell[280885, 9414, 108, 2, 70, "Input"],
Cell[280996, 9418, 473, 15, 70, "Text",
Evaluatable->False],
Cell[281472, 9435, 138, 3, 70, "Text",
Evaluatable->False],
Cell[281613, 9440, 178, 4, 70, "Special1",
Evaluatable->False],
Cell[281794, 9446, 1539, 52, 70, "Text",
Evaluatable->False],
Cell[283336, 9500, 1063, 34, 70, "Text",
Evaluatable->False],
Cell[284402, 9536, 767, 23, 70, "Text",
Evaluatable->False],
Cell[285172, 9561, 139, 3, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[285334, 9566, 91, 2, 70, "Subsection",
Evaluatable->False],
Cell[285428, 9570, 920, 27, 70, "Text",
Evaluatable->False],
Cell[286351, 9599, 505, 8, 70, "Special1",
Evaluatable->False],
Cell[286859, 9609, 565, 18, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[287456, 9629, 108, 2, 70, "Subsection",
Evaluatable->False],
Cell[287567, 9633, 487, 15, 70, "Text",
Evaluatable->False],
Cell[288057, 9650, 312, 6, 70, "Text",
Evaluatable->False]
}, Open ]]
}, Open ]]
}, Open ]],
Cell[CellGroupData[{
Cell[288419, 9658, 130, 3, 70, "Subsubtitle",
Evaluatable->False,
PageBreakAbove->True],
Cell[CellGroupData[{
Cell[288572, 9663, 85, 2, 70, "Section",
Evaluatable->False],
Cell[288660, 9667, 1509, 38, 70, "Text",
Evaluatable->False],
Cell[290172, 9707, 148, 4, 70, "Special1",
Evaluatable->False],
Cell[290323, 9713, 841, 22, 70, "Text",
Evaluatable->False],
Cell[291167, 9737, 1628, 48, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[292827, 9787, 100, 2, 70, "Section",
Evaluatable->False],
Cell[292930, 9791, 1192, 39, 70, "Text",
Evaluatable->False],
Cell[294125, 9832, 2320, 74, 70, "Text",
Evaluatable->False],
Cell[CellGroupData[{
Cell[296468, 9908, 299, 10, 70, "Subsection",
Evaluatable->False],
Cell[296770, 9920, 1444, 43, 70, "Text",
Evaluatable->False],
Cell[298217, 9965, 1209, 27, 70, "Text",
Evaluatable->False],
Cell[299429, 9994, 174, 4, 70, "Special1",
Evaluatable->False],
Cell[299606, 10000, 365, 14, 70, "Text",
Evaluatable->False],
Cell[299974, 10016, 212, 4, 70, "Special1",
Evaluatable->False],
Cell[300189, 10022, 2085, 70, 70, "Text",
Evaluatable->False],
Cell[302277, 10094, 2086, 66, 70, "Text",
Evaluatable->False],
Cell[304366, 10162, 198, 4, 70, "Special1",
Evaluatable->False],
Cell[304567, 10168, 369, 14, 70, "Text",
Evaluatable->False],
Cell[304939, 10184, 402, 7, 70, "Text",
Evaluatable->False],
Cell[305344, 10193, 409, 7, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[305785, 10202, 403, 15, 70, "Subsection",
Evaluatable->False],
Cell[306191, 10219, 1786, 62, 70, "Text",
Evaluatable->False],
Cell[307980, 10283, 93, 2, 70, "Text",
Evaluatable->False],
Cell[308076, 10287, 441, 15, 70, "Text",
Evaluatable->False],
Cell[308520, 10304, 819, 12, 70, "Text",
Evaluatable->False],
Cell[309342, 10318, 167, 4, 70, "Text",
Evaluatable->False],
Cell[309512, 10324, 97, 2, 70, "Text",
Evaluatable->False]
}, Open ]],
Cell[CellGroupData[{
Cell[309641, 10328, 358, 13, 70, "Subsection",
Evaluatable->False],
Cell[310002, 10343, 1945, 61, 70, "Text",
Evaluatable->False],
Cell[311950, 10406, 1390, 33, 70, "Text",
Evaluatable->False],
Cell[313343, 10441, 92, 2, 70, "Text",
Evaluatable->False],
Cell[313438, 10445, 835, 25, 70, "Text",
Evaluatable->False]
}, Open ]]
}, Open ]]
}, Open ]]
}, Open ]]
}
]
*)
(***********************************************************************
End of Mathematica Notebook file.
***********************************************************************)