设置从 Mathematica 中调用的外部函数

Mathematica 中调用在外部程序中定义的函数时,需要增添适当的 MathLink 代码以传递函数的变量和得到函数所产生的结果.

在简单情况下,对每一个外部函数给出一个适当的 MathLink 模板就可以生成所需的代码.

:Begin:
:Function: f
:Pattern: f[x_Integer, y_Integer]
:Arguments: {x, y}
:ArgumentTypes: {Integer, Integer}
:ReturnType: Integer
:End:

包含外部函数 f 的 MathLink 模板的文件 f.tm.

:Begin:一个函数模板的开始
:Function:外部程序中的函数名
:Pattern:调用该函数的方式
:Arguments:函数的变量
:ArgumentTypes:函数变量的类型
:ReturnType:函数返回值的类型
:End:一个函数模板的结束
:Evaluate:函数安装后计算 Mathematica 的输入

MathLink 模板的元素.

对一个外部函数建立了 MathLink 模板后,必须将这个模板和实际的函数源代码结合起来. 当源代码是用 C 语言编写的时候,只需要简单地增加一个包含标准 MathLink 头文件的行,再插入一个小主程序即可.

包含标准 MathLink 头文件.
#include "mathlink.h"
这里是函数 f 实际的源代码.
int f(int x, int y) {
return x+y;
}
这里建立了一个 Mathematica 能调用的外部程序.
int main(int argc, char *argv[]) {
return MLMain(argc, argv);
}

一个含有 C 源代码的文件 f.c.

注意,不同系统调用的 main 的形式会有小的差异. 在所使用计算机系统的 MathLink Developer Kit 版本说明中将会给出合适的形式.

mcc预处理和编译 MathLink 源文件
mprep预处理 MathLink 源文件

处理 MathLink 源文件的典型外部程序.

约定将 MathLink 模板放在形如 file.tm 的文件中. 这类文件也可以含有散步在不同函数模板中的 C 语言代码.

在建立了适当的文件后,就要处理 MathLink 模板信息,编译所有的源代码. 这一般需要运行各种外部程序,其细节依赖于所使用的计算机系统.

例如,在 Unix 中,MathLink Developer Kit 有一个名为 mcc 的程序,它对任何文件中以 结尾的 MathLink 模板进行预处理,然后对结果中的 C 源代码调用 . mcc 将命令行选项和其它文件直接传递给 cc.

预处理 f.tm,然后将所得 C 源文件和文件 f.c 一起进行编译.
mcc -o f.exe f.tm f.c
在当前 Mathematica 进程中安装二进制文件.
In[1]:=
Click for copyable input
Out[1]=
现在 调用外部函数 f(int x, int y),并将两个整数相加.
In[2]:=
Click for copyable input
Out[2]=
外部程序处理机器整数,所有这里给了一个奇怪的结果.
In[3]:=
Click for copyable input
Out[3]=

在 Windows 系统中,MathLink Developer Kit 一般包含一个名为 mprep 的程序,必须将要处理的 .tm 文件作为输入直接调用它. mprep 输出产生 C 源代码,它可以送往 C 编译器.

Install["prog"]安装外部程序
Uninstall[link]卸载外部程序
Links["prog"]显示与 有关的激活链接
Links[]显示所有激活链接
LinkPatterns[link]显示在一个链接中可以被计算的模式

处理外部程序的链接.

找出程序 f.exe 的链接.
In[4]:=
Click for copyable input
Out[4]=
这里显示可以用该链接计算的 Mathematica 模式.
In[5]:=
Click for copyable input
Out[5]=
Install 安装了一个用来执行一个适当的 函数的实际函数 .

处理 MathLink 模板文件时做两件基本事情:第一,用 :Pattern: 的给定值产生一个Mathematica 定义,它通过 MathLink 调用外部函数. 第二,用 :Function: 的给定值产生 C 源代码,它在外部程序中调用函数.

:Begin:
给出在外部程序中实际调用的 C 函数名.
:Function:      prog_add
给出建立定义的 Mathematica 模式.
:Pattern:       SkewAdd[x_Integer, y_Integer:1]
这两个列表元素的值就是要传递给外部的实际变量.
:Arguments:     {x, If[x > 1, y, y + x - 2]}
这里指定变量应该按整数传给 C 函数.
:ArgumentTypes: {Integer, Integer}
这里规定从 C 函数返回的值必须是整数.
:ReturnType:    Integer
:End:

MathLink 模板中, :Pattern: 的指定值都可以是任何 Mathematica 表达式. 对 的指定值在每次调用外部函数时计算. 计算的结果将作为变量列表传递给函数.

有时需要建立调用外部函数时不计算,而是只在第一次安装这个外部函数时计算的 Mathematica 表达式.

这可以用在 MathLink 模板中插入 :Evaluate: 指定值来实现. 在 :Evaluate: 之后给出的表达式可以持续多行,它在遇到第一个空行时结束,或者在遇到第一个字符不是空格或跳格键的行时结束.

这里指定安装外部程序时要建立一个对 的用法的信息.
:Evaluate:    SkewAdd::usage = "SkewAdd[x, y] performs
a skew addition in an external program."

在安装一个外部程序时,MathLink 模板文件中给出的指定值将顺序使用. 这意味着出现在 :Begin: 之前,在 :Evaluate: 中给出的表达式将在外部函数的定义建立之前计算.

这里是一些将在外部函数定义建立之前计算的 Mathematica 表达式.
:Evaluate:  BeginPackage["XPack`"]
:Evaluate: XF1::usage = "XF1[x, y] is one external function."
:Evaluate: XF2::usage = "XF2[x] is another external function."
:Evaluate: Begin["`Private`"]
这里指明要建立一个 Mathematica 函数 去调用外部 C 程序函数 f.
:Begin:
:Function: f
:Pattern: XF1[x_Integer, y_Integer]
:Arguments: {x, y}
:ArgumentTypes: {Integer, Integer}
:ReturnType: Integer
:End:
这里指明 Mathematica 中的函数 调用函数 g. 它的变量和返回值都是近似实数.
:Begin:
:Function: g
:Pattern: XF2[x_?NumberQ]
:Arguments: {x}
:ArgumentTypes: {Real}
:ReturnType: Real
:End:
这些 Mathematica 表达式是在外部函数定义建立之后计算. 它们结束了定义中使用的上下文.
:Evaluate:  End[ ]
:Evaluate: EndPackage[ ]
这里是函数 f 实际的源代码. 该函数的变量名不一定要和 Mathematica 中对应的变量名相同.
int f(int i, int j) {
return i + j;
}
这里是 g 的实际源代码. 在 Mathematica 中给出的数字在传递给 g 之前自动转换为 C 的 double 型精度数.
double g(double x) {
return x*x;
}

:Evaluate: 设定值可以在第一次安装一个外部程序时计算 Mathematica 表达式. 此时也可以通过在调用 MLMain() 之前将代码插入 main() 中执行外部程序中的代码. 这在使用外部程序中的函数之前对它进行初始化时是有用的.

MLEvaluateString(stdlink,"string")计算一个字符串将其作为 Mathematica 输入

从外部程序中执行 Mathematica 命令.

int diff(int i, int j) {
i < j 时计算 Mathematica 函数 Print.
    if (i < j) MLEvaluateString(stdlink, "Print[\"negative\"]");
return i - j;
}
安装一个含有前面定义的 diff 函数的外部程序.
In[7]:=
Click for copyable input
Out[7]=
调用 diff 去执行 Print.
In[8]:=
Click for copyable input
Out[8]=

注意由 MLEvaluateString() 要求的计算所产生的结果将被忽略,要使用这些结果时需要 "与外部程序的双向通讯方式" 节中讨论的 Mathematica 与外部程序通讯的两种方式.

New to Mathematica? Find your learning path »
Have a question? Ask support »