6.テンプレートエンジンClearSilverを適用
さて今度は自動生成したApache Moduleに、「ClearSilver」を適用します。C言語のみで画面出力を行おうとすると処理が煩雑になってしまうためです。ClearSilverはバグトラッキングツール「Trac」でも使用されているC言語で作成されたテンプレートエンジンです。JavaのWebアプリケーションで言うところのJSPなど画面表示を担当する箇所とイメージしてもらうとわかりやすいかもしれません。
この章で行う作業は以下のとおりです。
- Apache Moduleの修正
- Makefileの修正
- テンプレートファイルの作成
- Apache Moduleの動作確認
Apache Moduleの修正
まずは、Apache Moduleの修正から行いましょう。
- P3\test\mod_test.c (サンプルコードはこちら)
40 #define ap_psprintf apr_psprintf 41 42 #include "httpd.h" 43 #include "http_config.h" 44 #include "http_protocol.h" 45 #include "ap_config.h" 46 #include "ClearSilver.h" 47 48 49 static NEOERR *render_cb(void *obj, char *s) 50 { 51 request_rec *r = (request_rec *)obj; 52 ap_rputs(s, r); 53 return STATUS_OK; 54 } 55 56 static void output_handler(request_rec *r) 57 { 58 HDF *hdf; 59 CSPARSE *cs; 60 61 const char *arrayname[4] = { "FOO", "BAR", "HOGE", "MONA" }; 62 int i; 63 hdf_init(&hdf); 64 65 for( i = 0; i < 4; i++ ) 66 { 67 hdf_set_value(hdf, ap_psprintf(r->pool, "csdata.%d.arrayname", i ), arrayname[i] ); 68 } 69 70 cs_init(&cs, hdf); 71 cs_parse_file(cs, "/usr/local/src/modtest/test/test.cs"); 72 cs_render(cs, r, render_cb); 73 cs_destroy(&cs); 74 hdf_destroy(&hdf); 75 } 76 77 78 79 /* The sample content handler */ 80 static int test_handler(request_rec *r) 81 { 82 83 if (strcmp(r->handler, "test")) { 84 return DECLINED; 85 } 86 87 r->content_type = "text/html"; 88 89 if (!r->header_only) 90 output_handler(r); 91 return OK; 92 } 93 94 static void test_register_hooks(apr_pool_t *p) 95 { 96 ap_hook_handler(test_handler, NULL, NULL, APR_HOOK_MIDDLE); 97 } 98 99 /* Dispatch list for API hooks */ 100 module test_module = { 101 STANDARD20_MODULE_STUFF, 102 NULL, /* create per-dir config structures */ 103 NULL, /* merge per-dir config structures */ 104 NULL, /* create per-server config structures */ 105 NULL, /* merge per-server config structures */ 106 NULL, /* table of config file commands */ 107 test_register_hooks /* register hooks */ 108 }; 109
ClearSilverの関数を使用するため、46行目でヘッダファイル「ClearSilver.h」をインクルードしています。以下に使用する関数を記載します。これらの関数についてはmanコマンドでAPIを調べることができます。
#include <cs/cs.h>
NEOERR *cs_init (CSPARSE **parse, HDF *hdf);
#include <cs/cs.h> NEOERR *cs_parse_file (CSPARSE *parse, const char *path);
#include <cs/cs.h> NEOERR *cs_render (CSPARSE *parse, void *ctx, CSOUTFUNC cb);
#include <cs/cs.h> void cs_destroy (CSPARSE **parse);
参考までに上記3つの各関数の戻り値である構造体NEOERR
は以下のようになっています。
util/neo_err.h(50行目から61行目) typedef struct _neo_err { int error; int err_stack; int flags; char desc[256]; const char *file; const char *func; int lineno; /* internal use only */ struct _neo_err *next; } NEOERR;
テンプレートファイルとのデータ授受には多次元データを表す汎用形式hdh(Hierarchical Data Format)を使用するため、これに関連する関数も使用することになります。この関数もmanコマンドを利用することによってAPIを調べることができます。
#include <util/neo_hdf.h>
NEOERR* hdf_init (HDF **hdf);
#include <util/neo_hdf.h> NEOERR* hdf_set_value (HDF *hdf, const char *name, const char *value);
#include <util/neo_hdf.h> void hdf_destroy (HDF **hdf);
なお、40行目は単純に「ap_psprintf」を「apr_psprintf」と定義しています。ヘッダファイルを作成する量ではないので、直接ソースファイルに記載しても問題ないとの判断したためです。また、apr_psprintf
のAPIは以下のとおりです。
APR_DECLARE_NONSTD(char *) apr_psprintf(apr_pool_t *p, const char *fmt, ...) __attribute__((format(printf,2,3)));
Makefileの修正
ClearSilverの利用に伴いMakefileも変更する必要があります。
- P3\test\Makefile (サンプルコードはこちら)
1 ## 2 ## Makefile -- Build procedure for sample test Apache module 3 ## Autogenerated via ``apxs -n test -g''. 4 ## 5 6 builddir=. 7 top_srcdir=/usr/local/apache22 8 top_builddir=/usr/local/apache22 9 include /usr/local/apache22/build/special.mk 10 11 # the used tools 12 APXS=apxs 13 APACHECTL=apachectl 14 15 # additional defines, includes and libraries 16 #DEFS=-Dmy_define=my_value 17 #INCLUDES=-Imy/include/dir 18 #LIBS=-Lmy/lib/dir -lmylib 19 INCLUDES=-I/usr/local/include/ClearSilver 20 LIBS=-lneo_cs -lneo_utl 21 22 # the default target 23 all: 24 $(APXS) -c $(INCLUDES) $(LIBS) -Wl,-g mod_test.c 25 26 # install the shared object file into Apache 27 install: install-modules-yes 28 29 # cleanup 30 clean: 31 -rm -f mod_test.o mod_test.lo mod_test.slo mod_test.la 32 33 # simple test 34 test: reload 35 lynx -mime_header http://localhost/test 36 37 # install and activate shared object by reloading Apache to 38 # force a reload of the shared object file 39 reload: install restart 40 41 # the general Apache start/restart/stop 42 # procedures 43 start: 44 $(APACHECTL) start 45 restart: 46 $(APACHECTL) restart 47 stop: 48 $(APACHECTL) stop 49
まずは、19行目の変数INCLUDES
に、ClearSilverのインクルードファイルの保管されているディレクトリを設定します。次に20行目の変数LIBS
に必要なライブラリファイルを登録します(下表参照)。最後に、24行目のallオプション指定時の記述に、変数INCLUDES
、LIBS
を含めたapxsによるコンパイルコマンドを登録すればMakefileの修正は完了です
ライブラリファイル | LIBへの登録要否 |
/usr/local/lib/libneo_cgi.a | 不要 |
/usr/local/lib/libneo_cs.a | 要 |
/usr/local/lib/libneo_utl.a | 要 |
テンプレートファイルの作成
最後にClearSilverのテンプレートファイル「test.cs」を作成しましょう。
- P3\test\test.cs (サンプルコードはこちら)
<?cs each:item = csdata ?> Hello <?cs var:item.arrayname ?>!<br> <?cs /each ?>
上記のコードではcsdataに登録されている要素数分ループを行い、プログラムで作成したhdfデータからarrayname要素の内容を表示する処理を行います。
Apache Moduleの動作確認
以上の準備が整ったところで動作の確認を行いましょう。まず、Apache HTTP Serverを停止した後、コンパイルとインストールを実行します。
apachectl stop make clean make all install
Make実行時にエラーが表示されなければ、モジュールの作成と「/usr/local/apache22modules」へのインストールが行われているはずです。
ここでApacheの起動を行います。「http://(ApahceHTTPサーバが動作しているホスト)/test/」にアクセスして、動作の確認を行いましょう。
apachectl start