在外部程序中运行 Wolfram 系统

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