AZ-Prolog ユーザーズマニュアル

## 9-4.CGIインターフェース

### 9-4-1.概要

Prologで書かれたCGIプログラムを翻訳・実行して動的なWEBページを実現するための枠組みを提供します。
本マニュアルでは、WEBサーバとしてApacheを前提として説明しています。
CGI用Prologインタプリタはソースファイル（prologcgi.pl）も提供されていますので、参考にしてください。

### 9-4-2.PrologによるCGIの利用方法

##### （1）apache のインストールとデモプログラム、環境の設定

最終的にサーバーでプログラムを公開するにしても、デバッグ・開発用にクライアントマシンにもApacheのインストールをしておくことをお勧めします。
Apacheは下記のいずれかの方法で入手・インストールできます。必要に応じて関連WEBサイト、書籍などをお読みください。
Apacheの入手・インストール方法（本マニュアル改訂時2014年6月現在）

1) | Apache Software Foundation（URL：http://www.apache.jp/）からソースを入手してインストール
2) | 同サイトからバイナリを入手してインストール（Windows32bitのみ）
3) | サードパーティのサイトからWindows64bit版バイナリを入手してインストール http://www.apachelounge.com/download/
4) | UbuntuソフトウェアセンターからApacheパッケージを入手してインストール $ sudo apt-get install apache2.2-common $ sudo apt-get install apache2-mpm-prefork ※この場合、コンフィグレーションが他と大きく異なります。
5) | Mac OS X でApacheパッケージを入手してインストール $ sudo port install apache2

AZ-Prologのトップサイト(http://www.az-prolog.com/)の「ラーニング(Learning)」のプルダウンメニューにある「CGIサンプルプログラム」で見れるのと同様のデモが、AZ-Prologのインストールディレクトリ下の「sample¥cgi_demo」に入っています。
このデモをローカルマシンのApache上にインストールして動かすには以下の手順に従います。環境によって一部動かないもの、手を加える必要のあるものがありますが、これについては手順表の下の注意書きをご覧ください。

CGIサンプルデモを見るための手順

1) | AZ-Prologのサンプルディレクトリ(sample¥cgi_demo¥cgi-bin)にある全ファイルをApacheのcgi-binへコピー
2) | AZ-Prologのサンプルディレクトリ(sample¥cgi_demo¥htdocs)にある全ファイル・ディレクトリをApacheのドキュメントルートへコピー
3) | ODBCのデモ(Windows版のみ）には、あらかじめ設定が必要です。 AZ-Prologの拡張機能ODBCの提供サンプルソース(sample¥odbc¥odbc_test.pl)に書かれている方法でODBCのDNS（同名、同ログイン名/パスワード）を設定し、同じファイルをインタプリタに読み込んでテーブル及びデータを生成しておいてください。ODBCについては9-9.ODBCを参照してください。
4) | 日本語形態素解析器：MeCab、及び日本語係り受け解析器：CaboCha（Windows版32bitのみ）のデモのためには、これらのインストールが必要です。詳細は9-5.Mecab/Cabochaを参照してください。
5) | Windows版Apache(32,64bitとも）では、httpd.confの任意の場所に次の設定を追記してください。
    PassEnv AZPROLOG
Windows版Apache64bitでは、 5-1) コントロールパネルのシステム環境変数の設定で「MECABのインストールフォルダ¥etc¥mecabrc」を設定します。 [変数名]　MECABRC [値(例)]　C:¥Program Files (x86)¥MeCab¥etc¥mecabrc 5-2)　httpd.confの任意の場所に次の設定を追記してください。
    PassEnv MECABRC
httpd.confを書き換え後、コントロールパネル->管理ツール->サービスでApacheを再起動します。
6) | 上記が終了しましたら、ブラウザを開き、アドレス欄に次の入力でデモを開始することができます（Apacheが動作していなければならないのは勿論です）。 http://localhost/az_index.html

注意：

1) | Linux版またはMac OS X版で「ソースを表示する」を選ぶと、エラーになります。 system/pl/puttext.plをコンパイルしてcgi-binの下に置いてください。コンパイル方法は同ファイルに書かれています。
2) | Nクイーンのバイトコード版やフルコンパイル版が正しく動かない場合は、cgi-binの下にあるqueen.cgiをコンパイルしてください。コンパイル方法は同ファイルに書かれています。
3) | 鬼車、MeCab、ODBCなどで正しく表示されない場合は、拡張機能の対応するマニュアルも参照してください。

### 9-4-3.PrologによるCGIの書き方

以下、PrologでCGIプログラムを書く場合のポイントについて順に説明します。

##### (1) CGI用Prologインタプリタの指定

Prologで記述するCGIのソースコードの一行目にCGI用Prologインタプリタを記述します。これにより、それに続くPrologのソースコードが解釈実行され、CGIプログラムとして機能します。
インタプリタ名のみで指定する場合と、フルパスで指定する場合とがあります。開発環境から本番環境へ移行する際、前者はそれぞれの環境でprologcgiのPATHが通っていればそのまま動きますが、さもなければ見つかりません。後者はPATHが通っていなくても実行が可能ですが、両環境でAZ-Prologのインストールディレクトリが異なる場合には動きません。それぞれ一長一短があります。

＜例：インタプリタ名のみ指定する場合＞

    #! prologcgi

＜例：フルパスで指定する場合（Windows 64bit版の例）＞

    #! C:¥Program Files¥AZ-Prolog.8xx¥bin¥prologcgi

＜例：フルパスで指定する場合（Ubuntu版標準インストールの例）＞

    #! /usr/local/bin/prologcgi

＜例：フルパスで指定する場合（Mac版標準インストールの例）＞

    #! /Applications/azprolog.app/Contents/az_home/bin/prologcgi

##### (2) トップレベル述語の指定

PrologCGIの起動直後に呼び出される処理を指定するには、トップレベルの述語(top_call/0)をソースコードに必ず記述します。

    top_call:- 処理.

処理の部分に記述するのは、CGIの起動を要求（HTTPリクエスト）したブラウザ画面から送られたパラメタを取得し、それに基づいて処理を行って、次に遷移すべき動的なページを構成して標準出力（つまりブラウザ）に返す（HTTPレスポンス）と言う一連の流れのコードです。これらを記述するための各種組込述語が提供されています（「(6)CGI用拡張組込述語」を参照）。

##### (3) ページコンテンツの出力

HTTPレスポンスの本体をHTMLの構文規則に沿って記述し出力を行いますが、その前にHTTPレスポンスヘッダの一部としてコンテンツの種類や文字コードを表す行（下記はその一例）を出力します。ステータスコードやその他のヘッダ情報はWEBサーバが付加してくれます。

    Content-Type: text/html; charset=utf-8

AZ-PrologのCGIインターフェースでは、HTML中に変数の値や処理の結果（述語呼び出しの結果出力）を動的に埋め込むことができます。HTMLの詳細については他の説明書などをお調べください。ブラウザでの改行表示は
だけで十分ですが、出力したHTMLをソース表示した場合などの見やすさを考慮し、「nl」を補っておくといいでしょう。

##### (4) バイトコードコンパイルによる高速化

Prologで記述されたCGIプログラムをバイトコードコンパイルすることにより、インタプリタコード（Prologソースコードをインタプリタに読み込んだコード）を解釈実行する場合と比較して、実行スピードを4倍程度速くすることが可能です。
バイトコードコンパイルはAZ-Prologコンパイラ(azpc）を使って容易に行えます。
＜例：queens.cgiをバイトコードコンパイルする場合＞

    C:¥>azpc -p queens.cgi /byte
    C:¥>ren queens.b queenb.cgi

バイトコードコンパイルでは、拡張子「.b」の付いたファイルが生成されますが、バイトコードに変換したCGIプログラムであることを明確にするために、上の例では名前を変更しています。

##### (5) フルコンパイルで更に高速化、多機能化

prologで書かれたCGIプログラムをフルコンパイルすると、10倍程度実行スピードが上がります。フルコンパイルするには、AZ-Prologのインストールディレクトリ下、system¥plにあるprologcgi.pl、utility.plを同時にコンパイルリンクします。コンパイルオプションに、「/no」と「/dcurses」を指定してください。以下の例では分かり易くするためにパスは省略しています。
＜例：queens.cgiをフルコンパイルする場合＞

    C:¥>azpc -p queens.cgi utility.pl  prologcgi.pl  /fast  /e queens  /no  /dcurses

フルコンパイルでは、本パッケージで提供される拡張機能（鬼車、めかぶ、かぼちゃ、Redis他）をリンクすることで、サーバサイドのWEBアプリケーションとしての多機能化を実現するすることができます。拡張機能を利用したり複数モジュール間の連携にはpublic宣言、extern宣言等の各種宣言が必要になります。これについては「7.コンパイラ」の章を参照してください。

##### (6) CGI用拡張組込述語

PrologでCGIプログラムを記述する際に利用できる拡張組込述語について解説します。

get_param/2 | CGI呼び出しの際のパラメータを取得する。指定パラメータと一致するものがないときは失敗する。HTTPリクエストがGETメソッドの場合もPOSTメソッドの場合も同列に扱える。
第1引数： | パラメータ名 呼び出し元がHTMLの場合は、パラメータ名はsubmitされたformのinputタグのname属性の値に相当する。
第2引数： | パラメータの値（出力） ファイル送信の場合は{ファイル名、受信データタイプ、ファイル内容}の書式となる。
下記のようなformからファイル(仮にfile.dat、中身が"aaa")が送信された場合は、 パラメータ名：user_file パラメータ値：{file.dat, application/x-ns-proxy-autoconfig, aaa} のようになる。
    ‹form enctype='multipart/Form-data' action='/cgi-bin/xxxx.cgi' method='POST'>
    ‹input type='file' name='user_file'>
    ‹input type='submit' value='Upload'>
    ‹/form>
[ html_call/1 ] | 標準出力（ブラウザ）にヘッダ、HTMLタグを出力する。
第1引数： | 出力内容のリスト リストの要素に応じて以下のように処理される。 ・要素が文字列なら1文字ずつ順に出力される。 ・要素が変数なら値が出力される。 ・要素が組込述call/1の呼び出し形式なら、引数のゴールが実行される。 （ゴールの出力内容が埋め込まれる）
ヘッダとHTML開始タグの間には空行が必要になる（下記の例）。
    html_call([

        "Content-Type: text/html; charset=utf-8

        <html><head/><body>

          ......
[html_tmplate/1] | テンプレート機能を利用して標準出力（ブラウザ）にヘッダ、HTMLタグを出力する。変数名と値の対応情報は予め単位節「tmp_name(変数名,値).」の形で定義する。html_tmplate/2の下位述語。
第1引数： | テンプレートファイル名（アトム）
テンプレートファイル中で使用できる置き換え用タグは以下の２つ。 1)書式： 変数名の指す変数が値を持っていれば値に置き換える。 2)書式： ...条件出力部分... 変数名の指す変数が値を持っていれば条件出力部分を出力する。 条件出力部分に1)のタグを入れ子にすることも可能。 <参考> tmp_mane/2を単位節でなく以下の様な述語として記述すれば、データベースから取得した値での置き換えも可能になる。
    tmp_name(VarName,Value):-

    get_key(ID),select_each([Value],tmp_get,[ID,VarName]),!.
[html_tmplate/2] | テンプレート機能を利用して標準出力（ブラウザ）にヘッダ、HTMLタグを出力する。変数名と値の対応情報は引数で与える。
第1引数： | テンプレートファイル名（アトム）
第2引数： | 1)データファイル名（アトム）、または2)リスト 1)データファイルの場合：単位節「tmp_name(変数名,値).」が定義されたファイルをコンサルトする。 2)リストの場合：[変数名1=値1,変数名2=値2.....])の書式で与える。 単位節「tmp_name(変数名,値).」に焼き直されアサートされる。
単位節定義後はhtml_tmplate/1を呼び出す。
set_exit_timer/1 | Prologプロセスを強制終了する経過時間を設定する。 CGIに限らず、バグや誤入力でプロセスが終了せずサーバー負荷が高まるのを防ぐ。
第1引数： | 経過時間(整数値。単位：ミリセカンド）
    | ?-set_exit_timer(+整数).

##### (7) CGI利用時にシステムによって生成されるインタプリタコード

CGIプログラムから以下の情報が参照できます。

param_assoclist/1 | CGI呼び出し時の全パラメータ（名前と値）のリストを保持する単位節。チェックリストのように同一のname属性を持つInputタグが複数ある場合でも、このリストから全てを取得できる(get_param/2では名前の一致する先頭要素の値のみ）。
    | ?-param_assoc_list(-ﾘｽﾄ).
    リスト＝[タグ1、値1、タグ2、値2、タグ3、値4 ......]
my_cgi_name/1 | CGIプログラムのファイル名を保持する単位節。
    | ?-my_cgi_name(？アトム).

##### (8) CGIプログラムのコマンドラインでの動作確認方法

パラメータ渡しのCGI呼出しは次のようにします。ブラウザに送られるHTML出力がコンソールに表示されます。

     c:¥>prologcgi queens.cgi?”num=8&disp=true”

▲