在外部程序中运行 Mathematica
在外部程序中运行 Mathematica 需要利用 MathLink 的许多特点. 第一个问题是如何将 MathLink 连接到Mathematica.
用 MathLink 模板产生能从 Mathematica 调用的外部程序时,建立 MathLink 连接的源代码会自动产生,在外部程序中要做的就是调用 MLMain(argc, argv). 但一般要调用几个函数去建立 MathLink 连接.
| MLENVMLInitialize(0) | 初始化 MathLink 库函数 |
| MLINKMLOpenArgcArgv(MLENV env,int argc,char**argv,int*errno) | |
| 打开一个 MathLink 连接,从 | |
| MLINKMLOpenString(MLENV env,char*string,int*errno) | |
| 打开一个 MathLink 连接,从一个字符串取参数 | |
| intMLActivate(MLINK link) | 激活一个 MathLink 连接,等待另一端的程序响应 |
| voidMLClose(MLINK link) | 关闭 MathLink 连接 |
| voidMLDeinitialize(MLENV env) | 取消对 MathLink 库函数的初始化 |
#include "mathlink.h"
int main(int argc, char *argv[]) {
MLENV env;
MLINK link;
int errno;
env = MLInitialize(0);
link = MLOpenArgcArgv(env, argc, argv, &errno);
MLActivate(link);
...
}
传递给 MLOpenArgcArgv() 的
常常是直接从整个程序开始时传递给
的
得到.
在
数组中的元素是字符串,它反映 Mathematica 函数 LinkLaunch、LinkCreate 和 LinkConnect 的变量选项.
| "-linklaunch" | 像 LinkLaunch["name"] 一样的运算 |
| "-linkcreate" | 像 LinkCreate["name"] 一样的运算 |
| "-linkconnect" | 像 LinkConnect["name"] 一样的运算 |
| "-linkname","name" | 给出要使用的名称 |
| "-linkprotocol","protocol" | 给出要用的连接协议( |
可能传递给 MLOpenArgcArgv()的
数组元素.
MLOpenArgcArgv() 的另一种选择是 MLOpenString(),它将参数并置在一个字符串中,参数中间有空格.
打开 MathLink 到 Mathematica 内核的连接后,就能用标准的 MathLink 函数交换数据.
| intMLEndPacket(MLINK link) | 指明包的结尾 |
| intMLNextPacket(MLINK link) | 寻找下一个包的头部 |
| intMLNewPacket(MLINK link) | 跳到当前包的结尾 |
用 MLPutFunction() 等发生了所有包以后,MathLink 要求调用 MLEndPacket() 去确认同步性和一致性.
在编写与 Mathematica 内核直接通讯的外部程序时,一个主要的方面是处理内核可以产生的各种包.
函数 MLNextPacket() 寻找下一个来自于内核的包的头部,返回一个表面该包类型的常数.
Mathematica 包 | 常数 | |
| ReturnPacket[expr] | RETURNPKT | 计算结果 |
| ReturnTextPacket["string"] | RETURNTEXTPKT | 结果的文本形式 |
| InputNamePacket["name"] | INPUTNAMEPKT | 输入行名称 |
| OutputNamePacket["name"] | OUTPUTNAMEPKT | 输出行名称 |
| TextPacket["string"] | TEXTPKT | Print 等函数的文本输出 |
| MessagePacket[symb,"tag"] | MESSAGEPKT | Mathematica 产生的消息名称 |
| InputPacket["prompt"] | INPUTPKT | 响应 Input 函数的请求 |
| CallPacket[i,list] | CALLPKT | 调用外部函数的请求 |
MLNextPacket() 识别的一些包.
while ((p = MLNextPacket(link)) && p != RETURNPKT)
MLNewPacket(link);
将一个完整的前端写入 Mathematica 时,需要处理产生的各种类型的包. 一般是在 MLNextPacket()返回值上设置一个适当的转换来完成这一任务.
MathLink Developer Kit 含有几个简单但完整的前端源代码的样本.
| intMLReady(MLINK link) | 测试链接中是否有待读的数据 |
| int MLReadyParallel (MLENV e, MLINK *links, int n, mltimeval t) | |
| 并行测试链接列表中是否有待读的数据 | |
| intMLFlush(MLINK link) | 刷新含有链接中待送数据的缓冲区 |
诸如前端等更复杂的外部程序的特定之一是在等待从 Mathematica 发送的数据时进行运算. 而在调用 MLNextPacket() 等标准 MathLink 库函数时,直到该函数所需的数据备齐前,程序是锁住的.
反复调用 MLReady()可避免锁住,当 MLReady() 返回的不是
值时,仅调用 MLNextPacket() 等函数即可. MLReady() 与 Mathematica 函数 LinkReadyQ 相似.
注意,MathLink 有时会将要发送的数据放在缓冲区内. 为了保证所有数据被送出. 应该调用 MLFlush(). 这之后调用 MLReady() 和等待返回的数据才有意义.
