2.12.12 外部程序中的表达式操作Mathematica 表达式提供了处理各种数据的一般方法,有时需要在外部程序 中使用这些表达式. C 语言等并没有提供保存一般 Mathematica 的直接方式, 但这可以用 MathLink 库中提供的回路链接 ( ) 来完成. 回路链接是外部程序 中的局部 MathLink 连接,可以向它写入后面读出的表达式. 操作回路链接的函数
...
打开一个回路链接
ml = MLLoopbackOpen(stdenv, &errno);
将表达式 Power[x, 3] 放入回路链接中
MLPutFunction(ml, "Power", 2); MLPutSymbol(ml, "x"); MLPutInteger(ml, 3);
...
从这个回路链接中读出该表达式
MLGetFunction(ml, &head, &n); MLGetSymbol(ml, &sname); MLGetInteger(ml, &k);
...
重新关闭这个回路链接
MLClose(ml);
可以用 MLTransferExpression() 去取一个通过 stdlink 从 Mathematica 中得到的一个表达式,然后把它保存在局部回路链接中以便后面处理. 也可以用 MLTransferExpression() 去取在局部回路链接中建立的表达式, 然后再通过 stdlink 将它送回到 Mathematica 中.
...
将 21! 放到一个局部回路链接中
MLPutFunction(ml, "Factorial", 1); MLPutInteger(ml, 21);
这里将头 FactorInteger 送到 Mathematica
MLPutFunction(stdlink, "FactorInteger", 1);
这里将 21! 从回路链接传送到 stdlink
MLTransferExpression(stdlink, ml);
可以将任意表达式序列放入回路链接中. 一般可以按放入的顺序取出这些 表达式. 从链接取出一个表达式后它就不再保存. 但可以用 MLCreateMark() 去标记一个链接中表达式序列的某一位置,强制 MathLink 去保存该标记 之后的表达式以便后面访问. 在 MathLink 设置标记
...
将整数 45 放入回路链接中
MLPutInteger(ml, 45);
再将 33 放入该链接中
MLPutInteger(ml, 33);
再将 76 放入
MLPutInteger(ml, 76);
这里从该链接读出 45, 45 就不再保存
MLGetInteger(ml, &i);
这里在链接的当前位置插入一个标记
mark = MLCreateMark(ml);
现在读 33
MLGetInteger(ml, &i);
接着读 76
MLGetInteger(ml, &i);
这里返回到标记位置
MLSeekMark(ml, mark, 0);
现在可以重新读 33
MLGetInteger(ml, &i);
重要的一点是完成之后要删除这些标记,避免保存那些不必要的表达式
MLDestroyMark(ml, mark);
MathLink 库提供的方法在打开和关闭回路链接中以及产生和删除它们 之间的标记时是十分有效的. 要记住在一个链接中设立了标记后, MathLink 就保存该链接中在标记后的表达式,且保存一直持继到 标记删除为止. 从一个链接得到一些表达式的函数 MLGetNext( ) 返回的常数
switch(MLGetNext(ml)) {
这里读一个组合函数
case MLTKFUNC: MLGetArgCount(ml, &n); recurse for head for (i = 0; i < n; i++)  recurse for each argument  ...
这里读一个符号
case MLTKSYM: MLGetSymbol(ml, &name); ...
读一个机器整数
case MLTKINT: MLGetInteger(ml, &i); ...
}
用 MLGetNext() 可以直接写出能读任何表达式的程序. MathLink 的工作方式是, 函数的头部和变量作为相继的表达式在链接中出现,就可以逐个读入它. 注意,如果已经知道一个函数的头部是一个符号时,就可以用 MLGetFunction(), 而不用 MLGetNext(). 这时,需要调用 MLDisownSymbol() 去释放 符号名占用的内存. 向链接放表达式的函数 MLPutNext() 给出使用从 mathlink.h 头文件得到的 MLTKFUNC 常数的表达式类型, 这与 MLGetNext() 相同.
|