外部プログラムを Mathematica から呼び出す
外部プログラム中に定義してある関数を Mathematica から呼び出すためには,関数に引数を渡したり,関数の結果を Mathematica に戻すためのコードを外部プログラムに追加する必要がある.
簡単なものなら,呼び出したい外部関数ごとに適切な 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 テンプレートは関数のソースコードと結合させる必要がある.ソースコードがC言語で書かれていると仮定すると,それは単に MathLink のヘッダファイルを含むコード1行と小さいmainプログラムをソースコードに追加するだけで済む.
#include "mathlink.h"
int f(int x, int y) {
return x+y;
}
int main(int argc, char *argv[]) {
return MLMain(argc, argv);
}
システムによっては,main関数の形式が若干異なることもある.詳しくは MathLink デベロッパキット中のリリースノートを参照すること.
MathLink テンプレートは通常 file.tmという名前のファイルにする.そのファイルにはさまざまな関数のテンプレートに混ざって,Cのソースコードも挿入することができる.
適当なファイルを準備したら,MathLink テンプレートに書き込まれた情報とともに,ソースコードをコンパイルする.コンパイルは外部プログラムで行うが,細かい部分はコンピュータシステムによって違っている.
Unixを例に取ると,MathLink デベロッパキットにはmccと呼ばれるプログラムがあり,このプログラムは名前が.tmで終る MathLink テンプレートファイルを前処理してCのソースコードを生成し,そのソースコードをccでコンパイルする.mccはコマンドラインオプションや他のファイルは直接ccに渡す.
mcc -o f.exe f.tm f.c
| In[1]:= |
| Out[1]= |
| In[2]:= |
| Out[2]= |
| In[3]:= |
| Out[3]= |
Windowsでは,MathLink デベロッパーキットには,mprepプログラムが入っていて,これを直接呼び出して,前処理したい.tmファイルを処理する.mprepはCのソースコードを出力するので,それをCコンパイラにかける.
| Install["prog"] | 外部プログラムをインストールする |
| Uninstall[link] | 外部プログラムをアンインストールする |
| Links["prog"] | |
| Links[] | アクティブなリンクをすべて表示する |
| LinkPatterns[link] | あるリンク上で評価されるパターンを表示する |
| In[4]:= |
| Out[4]= |
| In[5]:= |
| Out[5]= |
MathLink テンプレートが処理されるとき,基本的に2つのことが行われる.まず,:Pattern:と
の仕様に従い,MathLink 経由で外部プログラムを呼び出す Mathematica の定義を生成する.次に,:Function:,
と
の仕様に従って外部プログラム中の関数を呼び出すCのソースコードが生成される.
:Begin:
:Function: prog_add
:Pattern: SkewAdd[x_Integer, y_Integer:1]
:Arguments: {x, If[x > 1, y, y + x - 2]}
:ArgumentTypes: {Integer, Integer}
:ReturnType: Integer
:End:
MathLink テンプレート中の:Pattern:と
には,どんな MathLink の式を与えても構わない.
に与えたものはすべて,その外部関数の呼出しごとに毎回評価される.評価の結果は引数のリストとして関数に渡される.
外部関数の呼出し時ではなく,インストール時にだけ,評価させたい Mathematica 式もあるだろう.
その場合,MathLink テンプレート中の:Evaluate:を利用する.:Evaluate:の後ろに与える式は何行になっても構わない.空行,あるいはスペース文字やタブ文字で始まらない行がきたら,式が終ったとみなされる.
:Evaluate: SkewAdd::usage = "SkewAdd[x, y] performs
a skew addition in an external program."
外部プログラムがインストールされるときは,MathLink テンプレートファイルに記述された順に仕様が読み込まれる.:Begin:より前の:Evaluate:に与えられた式は外部関数の定義が読み込まれる前に評価される.
:Evaluate: BeginPackage["XPack`"]
:Evaluate: XF1::usage = "XF1[x, y]は1つの外部関数です."
:Evaluate: XF2::usage = "XF2[x]は他の外部関数です."
:Evaluate: Begin["`Private`"]
:Begin:
:Function: f
:Pattern: XF1[x_Integer, y_Integer]
:Arguments: {x, y}
:ArgumentTypes: {Integer, Integer}
:ReturnType: Integer
:End:
:Begin:
:Function: g
:Pattern: XF2[x_?NumberQ]
:Arguments: {x}
:ArgumentTypes: {Real}
:ReturnType: Real
:End:
:Evaluate: End[ ]
:Evaluate: EndPackage[ ]
int f(int i, int j) {
return i + j;
}
double g(double x) {
return x*x;
}
:Evaluate:を利用して,外部プログラムが最初にインストールされるときに評価される Mathematica の式を指定することができる.また,外部プログラムのmain()中のMLMain()呼出しの前に挿入したコードも,外部プログラムのインストール前に実行される.外部関数が実行される前に,外部プログラムを初期化する場合等に使うとよいだろう.
| MLEvaluateString(stdlink,"string") | 文字列を Mathematica の入力として評価する |
外部プログラムから Mathematica のコマンドを実行する
int diff(int i, int j) {
if (i < j) MLEvaluateString(stdlink, "Print[\"negative\"]");
return i - j;
}
| In[7]:= |
| Out[7]= |
MLEvaluateString()の評価結果は,どんなものであろうと単に無視されることに注意すること.戻り値の利用には Mathematica と外部プログラムとの間で完全な双方向の通信が必要になる.これに関しては「外部プログラムとの双方向通信」で述べる.
