呼び出す関数は、以前書いたgnuplotへのpipeを開いて
コマンドを書き込む以下の関数。
/* gpdo.c */ #include <stdio.h> FILE *gpstart(void); void gpstop(FILE *p); void gpdo(FILE *p, char *s); FILE *gpstart(void) { /* start gnuplot process */ return popen("gnuplot.exe --persist", "w"); } void gpstop(FILE *p) { /* stop gnuplot process */ gpdo(p, "quit"); pclose(p); } void gpdo(FILE *p, char *s) { /* send command string to gnuplot process */ fprintf(p, s); fprintf(p, "\n"); fflush(p); }
Windowsのgcc(MinGW)で共有ライブラリにします。
gcc -shared -o gpdo.so gpdo.c出力されたgpdo.soをPharo.exeがあるフォルダに配置しました。
前と同様に、Pharoを起動してFFILibraryを継承したライブラリファイルを示す
クラスGnuplotDoLibを作成しました。そのクラスに、win32ModuleNameメソッド
を追加し、共有ライブラリのファイル名を返すようにします。
win32ModuleName ^ 'gpdo.so'
次は、関数呼び出し用のクラスを作ります。Objectクラスを継承してGnuplotDoクラスを
作りました。メソッドは関数を呼び出すだけなので、クラス側のメソッドにします。
これで、呼び出すときにわざわざインスタンスを生成する必要がなくなります。
三つの関数についてそれぞれメソッドを追加しました。
FILE構造体へのポインタ(FILE *)については、
今回はPharo側で解釈する必要がない(メンバーにアクセスしたりしない)ため、(void *)とします。
gpOpen ^ self ffiCall: #(void * gpstart ()) module: GnuplotDoLib. gpClose: aHandle self ffiCall: #( void gpstop (void * aHandle)) module: GnuplotDoLib gpHndl: aHandle gpCmd: aString self ffiCall: #( void gpdo (void * aHandle, String aString) ) module: GnuplotDoLib
これで準備完了です。Playgroundを開いて動かしてみます。
hndl := GnuplotDo gpOpen. GnuplotDo gpHndl: hndl gpCmd: 'set xlabel "x"'. GnuplotDo gpHndl: hndl gpCmd: 'set ylabel "y"'. GnuplotDo gpHndl: hndl gpCmd: 'plot sin(x)'. GnuplotDo gpClose: hndl.
とりあえず、これでPharoからgnuplotを起動してラベル設定してsin(x)を プロットする手続きが行えました。 エラーが起こるようなコマンドをgnuplotに渡すとgnuplotがクラッシュ してしまいますが、よしとします。