[実験] PHP を C/C++ の前処理に使う

C/C++ ではプリプロセッサを使うことができます。それによって単純なマクロ機能を使うことはできるわけですが、ちょっと凝ったことをしようとすると、すぐに役不足になってきます。例えば、配列の要素を事前に整列するとか、静的な二分木や三角関数表をつくるといったことは、プリプロセッサではできません。

通常、こうしたことを行うには、別途何らかのコードジェネレータを作って、それに C/C+ のソースコードを生成させることになるわけですが、もっと簡単な方法があればそれに越したことはありません。今回は、埋め込み型のスクリプト言語である PHP を使ってこれを実現することを試みます。

PHP というと、ウェブ専用の言語だと誤解している人もいるかもしれません。しかし、実際の PHP はコマンドラインでも使うことができますので、通常のスクリプト言語として扱うこともできるわけです。しかも、同じソースファイルに PHP のコードと他の言語のコードを混在できますから、今回の目的にはぴったりです。

なお、m4 のような強力なマクロプロセッサを使うという方法もありますが、m4 だと、C/C++ のキーワードと衝突する組み込みマクロがあったりと、いろいろ気を使う部分が少なくありません。その点、<?php と ?> で囲んだ部分だけが対象になる PHP は便利です。

今回は、固定小数点を用いた静的な三角関数表を作る前処理を PHP で記述する例を挙げます。

/* isin - 1.14固定小数点による正弦関数 */
int isin(int angle)
{
  static const short table[] = {
<?php
  for ($angle = 0; $angle <= 90; $angle++)
  {
    printf("%d,\n", (int)(sin(pi() * $angle / 180.0) * (2 << 14)));
  }
?>
  };
  int sign = 0;
  int result;
 
  if (angle < 0)
  {
    sign = 1;
    angle = -angle;
  }
  angle %= 360;
 
  if (angle > 180)
  {
    sign ^= 1;
    angle -= 180;
  }
  if (angle > 90)
  {
    angle -= 90;
  }
 
  result = table[angle];
  if (sign)
  {
    result = -result;
  }
  return result;
}

<?php と ?> で囲まれた部分が PHP のコードです。これをどうやってコンパイルするかですが、このソースファイルが isin.c というファイル名だった場合、

$ php isin.c | gcc -x c -

のようにすればOKです。コンパイルエラーが発生した場合に、エラーメッセージを読みやすくするためには、上のようにパイプラインで処理するより、いったん PHP が出力したコードをリダイレクトでファイルに書き込んだほうがよいかもしれません。

PHP で前処理を行う際に注意しなければならないことが一点あります。多くのスクリプト言語同様、最初の行に、

#!/usr/bin/php

のように書けるようにするため、先頭行に C/C++ の前処理指令を書くとおかしくなります。うっかり先頭行に #include を書くとこの問題に遭遇します。空行を設けるだけでもよいのですが、ファイルヘッダをコメントとして書いておくのが一番かと思います。

PHP で前処理を行うタイミングとして、C/C++ のプリプロセッサを通した後で PHP を実行することも考えられます。ただ、PHP では必須になる $ が C/C++ の基本ソース文字集合ではないので、処理系によってはうまくいかなくなる可能性もあります。また、PHP のコードそのものを C/C++ のマクロとすることもできるので、便利といえば便利なのですが、かなり凶悪なことができてしまうという問題もあります。

この方法を応用すれば、C/C++ だけでなく、Java や C# などの前処理に PHP を使うこともできるはずです。それどころか、ちょっと工夫すれば PHP 自体の前処理に PHP を使うことさえできます。懸案事項としては、統合開発環境での利用がやや面倒なのと、インテリセンスなどの入力補完機能が正しく働くかどうかわからない(未実験です)といったことが考えられます。

この記事のトラックバックURL:

http://www.kijineko.co.jp/trackback/550

[実験] PCP: C Preprocessor

名前付きの実引数が実現できるかも...

かなり前に書いた「可変個数の実引数の個数」や、本日書いた「マクロの可変個実引数の型を強制する」では、複合リテラルを使って何ができるかを模索しているわけです。この手のネタは