例題
Cコードの生成器を使って, Wolframのランタイムライブラリにリンクするスタンドアロンの実行ファイルを作成することができる.
ローパスフィルタ
この例題では,ローパスフィルタ用にスタンドアロンのCの実行ファイルを作成する.
実行ファイルの構築
targetDir = CreateDirectory[]次に離散ローパスフィルタを実装するコンパイルされた関数を定義する:
lowpass = Compile[{{x, _Real, 1}, dt, RC}, Module[{a = dt / (RC + dt), yprev = First[x], yi}, Table[yi = a * x[[i]] + (1 - a) * yprev;
yprev = yi;
yi, {i, 1, Length[x]}
]
]
];コード生成器を使ってターゲットディレクトリ内のCのソースファイルとヘッダファイルを保存する.
(* build the example in a specified directory *)
fnSource = FileNameJoin[{targetDir, "lowpass.c"}];
Export[fnSource, lowpass];
FileNames["*", targetDir]コードを実行するには,これを主要プログラムに埋め込む必要がある.以下は,生成されたコードを呼び出す適切なC関数である.
(* main function C source *)
lowpassmainSrc = "
#include \"stdio.h\"
#include \"stdlib.h\"
#include \"lowpass.h\"
#include \"WolframRTL.h\"
static WolframLibraryData libData = 0;
int main()
{
int err = 0;
mint i, type, rank, nelems, *dims;
double *data;
MTensor x, y;
double dt;
double RC;
libData = WolframLibraryData_new(WolframLibraryVersion);
/* read x */
type = MType_Real;
rank = 1;
dims = (mint*)malloc(rank * sizeof(mint));
scanf(\" %d\", &nelems);
dims[0] = nelems;
err = (*(libData->MTensor_new))(type, rank, dims, &x);
if (err) return 1;
free(dims);
data = (*(libData->MTensor_getRealData))(x);
for(i = 0; i < nelems; i++) {
scanf(\" %lf\", &(data[i]));
}
/* read dt */
scanf(\" %lf\", &dt);
/* read RC */
scanf(\" %lf\", &RC);
err = Initialize_lowpass(libData);
y = 0;
err = lowpass(libData, x, dt, RC, &y);
printf(\"%d\
\", err);
if(0 == err){
dims = (mint*)libData->MTensor_getDimensions(y);
nelems = dims[0];
data = (*(libData->MTensor_getRealData))(y);
printf(\"%d\
\", nelems);
for(i = 0; i < nelems; i++)
printf(\"%f\
\", data[i]);
}
Uninitialize_lowpass(libData);
return 0;
}
";(* create the main source file *)
lowpassmainSrcFile = FileNameJoin[{targetDir, "lowpassMain.c"}]
Export[lowpassmainSrcFile, lowpassmainSrc, "Text"];これで以下のようにスタンドアロンの実行ファイルを構築することができる.これは静的な最小ライブラリでリンクされる.このことによってライブラリパスを設定することが不要になる.この実行ファイルはプラットフォームに依存しない名前を使うので,すべてのプラットフォームで使えるはずである."SystemLibraries"オプションが{}に設定されることに注意されたい.このオプションは,MWolfram Symbolic Transfer Protocol (WSTP)ライブラリがリンクの段階では含まれないようにする.
Needs["CCompilerDriver`"];
lowpassExe = CreateExecutable[{fnSource, lowpassmainSrcFile}, "lowpass",
"SystemLibraries" -> {}, "TargetDirectory" -> targetDir, "Libraries" -> "WolframRTL_Static_Minimal"]このスタンドアロンの実行ファイルはそれだけで使用したり,他に渡したり,他のシステムに統合したりすることができる.
スタンドアロンのプログラムの実行
これでスタンドアロンのプログラムを実行することができる.実際のアプリケーションでは,ここで行ったようにWolfram言語からプログラムを実行することはない.以下は例として示す目的だけのものである.
まずいくつかの周波数成分を含む入力信号を生成する必要がある.
dt = 0.01;
RC = 0.3;
input = Table[Sin[x] + Sin[x * 10] + Sin[x * 50], {x, 0, 10, dt}];
ListPlot[input, ImageSize -> Medium, Joined -> True]スタンドアロンのプログラムは,以下の形式でその入力から読み込む.
nelems
elem #1
...
elem #n
dt
RC
これで信号から適切な形式の入力を作成することができる.これを以下に示す.
inputText = ExportString[Flatten[{Length[input], input, dt, RC}], "Text"];スタンドアロンの実行ファイルを実行し,結果をWolfram言語にロードしなおす.
process = StartProcess[lowpassExe];
WriteLine[process, inputText];
output = Import[process, "List"];結果はWolfram言語式に変換して検証することができる。最後に実際の数を抽出することができる.
output =
If[MatchQ[output, {0, x_ /; x + 2 === Length[output], ___}],
Drop[output, 2],
$Failed
];フィルタされた信号(赤)をもとの入力信号(青)と一緒にプロットする.
ListPlot[{input, output}, ImageSize -> Medium, Joined -> True]スタンドアロンのプログラムはWolfram言語から実行する必要はなく,どのような方法でも実行することができる.しかし,Wolfram言語からこれをテストして,その出力をこのように便利な方法で表示することができる.
DeleteDirectory[targetDir, DeleteContents -> True]スタンドアロンのリフティングウェーブレット変換
スタンドアロンのコード生成を使う例は,LiftingFilterDataのドキュメントの 「アプリケーション」 のセクションに示されている.