CommonLispで簡単なCプログラムの実行


はじめに

CommonLispで外部のプログラムを実行しようとしたとき,そのコマンドは処理系に大きく依存するので,僕の処理系での書き方をまとめておく.

今回は練習として,超絶簡単なCプログラムの実行を例に挙げる.

環境

OS:Mac OS X 10.11.3 El Capitan
処理系:Clozure CL(Emacs slime)

Cプログラムの作成

まずは実行するCプログラムを作成する.
今回は引数を一つ取り,その引数文字列をsample.txtへ書き込むだけのプログラムを作る.

sample.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){
  FILE *fp; //ファイルポインタ宣言

  /* ファイルを上書き形式でオープン */
  if((fp = fopen("sample.txt", "w+")) == NULL){
    exit(0); //例外処理
  }

  /* 文字列の書き込み */
  fprintf(fp, "引数の値は%sです\n", argv[1]);

  /* ファイルクローズ */
  fclose(fp);

  return 0;
}

なんのひねりもない面白くないプログラムですが,シェルを開いて

$ gcc sample.c -o sample

を入力してソースコードをコンパイル.

このプログラムが引数を一つとって動くことを実験.

$ ./sample 実験

と入力すると,それまでなかった以下のようなsample.txtが生まれている事がわかる.

CommonLispによるCプログラム実行

僕の環境はClozureCLなので,外部プログラム起動コマンドはccl:run-programだとのこと.

以下のコードで先ほど作成したプログラムを実行する.

exec.lisp
(defun ex-sample (input-text)
  (with-output-to-string (stream)
    (ccl:run-program "絶対パス/sample" `(,input-text) :output :stream)))

今回のrun-programの引数は1番目が実行するCプログラム,2番目がCプログラムの引数リスト,最後が出力先を表しているが,実際には更に複数のキーワードが用意されている.

これをロードして,

CL-USER> (load "絶対パス/exec.lisp")
#P"絶対パス/exec.lisp"
CL-USER> (ex-sample "wwwwwwwwwwwwwwwwww大草原wwwwwwwwwwwwwww")

とすると

というようにファイル内容が更新されたことが確認できた.

この時,with-output-string (stream)関数がないと成功しない(こんなことに数時間引っかかった)

最後に

処理系だけでなく起動するアプリケーションの形式によっても起動の仕方が変わるのかもしれない.
詳しく調べていないのでそれは追々調べていくということで...