PEAR::CodeGen_PECLでPHPのエクステンションを作成してみる
PHPでプログラムを組んでいると,時々既存のCのライブラリ関数を使いたくなるわけですが,PECLは敷居が高そうでこれまで調べたことはありませんでした。
たまたま,PEARのCodeGen_PECLを使うと割と簡単にできるらしい...という話がウエブに載っていたので,以前proj4のエントリで作ったProj.4のpj_fwd関数をPECLのエクステンションにしてみました。
まずはPEAR::CodeGen_PECLのインストール
% pear install -a codegen_pecl
さっそく定義ファイル(specファイル)の作成。これができればほとんど終了です。
XMLで概要,リリース情報,configureでチェックする内容,インクルードするファイル,リンクするライブラリ(この場合はlibproj.so)等々を記述し,<function>タグ以下の<code>タグ内(21行目以降)にCのコードを書けば終了です。
1 <?xml version="1.0" ?>
2 <extension name="proj4" version="1.0.0">
3 <summary>libproj PHP PECL extension</summary>
4 <description>libproj PHP PECL extension</description>
5 <release>
6 <version>1.0</version>
7 <date>2008-11-11</date>
8 <state>alpha</state>
9 <notes>
10 libproj pj_fwd test.
11 </notes>
12 </release>
13 <deps language="c" platform="unix">
14 <with name="libproj" defaults='/usr:/usr/local' testfile='include/projects.h'>
15 <header name="projects.h" />
16 <lib name="proj" platform="unix" function="pj_fwd" />
17 </with>
18 </deps>
19 <function name="proj4_pj_fwd">
20 <proto>array proj4_pj_fwd(float u, float v, array params)</proto>
21 <code><![CDATA[
22 //
23 // type check and count.
24 //
25 int num_params = 0;
26 zval** entry = NULL;
27 zend_hash_internal_pointer_reset(params_hash);
28 while (zend_hash_get_current_data(params_hash, (void**)&entry) == SUCCESS) {
29 if (Z_TYPE_PP(entry) == IS_STRING) {
30 num_params++;
31 }
32 else {
33 zval_dtor(return_value);
34 php_error(E_WARNING, "Argument 1 should be a proj parameter strings.");
35 RETURN_FALSE;
36 }
37 zend_hash_move_forward(params_hash);
38 }
39
40 char** str_params = malloc(sizeof(char*) * num_params);
41 if (!str_params) {
42 zval_dtor(return_value);
43 php_error(E_WARNING, "malloc() error.");
44 RETURN_FALSE;
45 }
46
47 int counter = 0;
48 zend_hash_internal_pointer_reset(params_hash);
49 while (zend_hash_get_current_data(params_hash, (void**)&entry) == SUCCESS) {
50 str_params[counter] = Z_STRVAL_PP(entry);
51 zend_hash_move_forward(params_hash);
52 counter++;
53 }
54
55 PJ* proj_param = pj_init(num_params, str_params);
56 if (!proj_param) {
57 zval_dtor(return_value);
58 php_error(E_WARNING, "pj_init() error.");
59
60 if (str_params)
61 free(str_params);
62
63 RETURN_FALSE
64 }
65
66 projUV idata;
67 idata.u = u * DEG_TO_RAD;
68 idata.v = v * DEG_TO_RAD;
69
70 projUV odata;
71 odata = pj_fwd(idata, proj_param);
72
73 struct FACTORS factors;
74 if (pj_factors(idata, proj_param, 0.0, &factors)) {
75 zval_dtor(return_value);
76 php_error(E_WARNING, "pj_factors() error.");
77
78 if (proj_param)
79 pj_free(proj_param);
80 if (str_params)
81 free(str_params);
82
83 RETURN_FALSE
84 }
85
86 add_assoc_double(return_value, "ns", odata.u);
87 add_assoc_double(return_value, "ew", odata.v);
88 add_assoc_double(return_value, "areal_scales", factors.s);
89 add_assoc_double(return_value, "convergence", factors.conv * RAD_TO_DEG);
90 char dms[256];
91 add_assoc_string(return_value, "convergence_dms", rtodms(dms, factors.conv, 0, 0), 1);
92
93 if (proj_param)
94 pj_free(proj_param);
95 if (str_params)
96 free(str_params);
97 ]]></code>
98 </function>
99 </extension>
完成したファイルを保存(proj4.xml)してあとは,
% pecl-gen -f proj4.xml
を実行すると,proj4ディレクトリが作成されます。
以降 proj4ディレクトリ内で
% cd proj4
% phpize
% ./configure --enable-proj4
% make
% sudo make install
でインストール完了。apacheを再起動すれば使えるようになります。
ブラウザでphpinfo()を実行するページを表示すると
と表示されますが,これは先のxmlファイルのタグの情報を表示するようです。
PHPで使用するコードは以下のような感じです。
1 <?php
2 $params = array("proj=tmerc",
3 "lat_0=33",
4 "lon_0=131",
5 "k=0.999900",
6 "x_0=0",
7 "y_0=0",
8 "ellps=GRS80",
9 "towgs84=0,0,0,0,0,0,0",
10 "units=m",
11 "no_defs");
12
13 $result = proj4_pj_fwd(131.396, 33.20960278, $params);
14
15 echo "NS : " . $result['ns'] . "\n";
16 echo "EW : " . $result['ew'] . "\n";
17 echo "Areal Scales : " . $result['areal_scales'] . "\n";
18 echo "Convergence : " . $result['convergence'] . "\n";
19 echo "Convergence : " . $result['convergence_dms'] . "\n";
20 ?>
といかにも簡単そうに書きましたが,Cのコードの部分はPECLの約束事があるので初めはかなり大変です。ただしなれてしまえば結構手軽に使えるので,重宝しそうです。
以下参考資料です。
リンク: [PHPプロ!] = Do You PHP? =PEAR::CodeGen_PECLを使ってPECLモジュールを作ってみる:CodeZine.
| 固定リンク
トラックバック
この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/142859/43086967
この記事へのトラックバック一覧です: PEAR::CodeGen_PECLでPHPのエクステンションを作成してみる:

コメント