Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

PEAR::CodeGen_PECL事始め


なかなか触れずにいたんですが、ちょっとだけ時間ができたので使ってみました。

インストールと動作確認

# pear install -a codegen_pecl
# pecl-gen
Usage:

pecl-gen [-h] [--force] [--experimental] [--version]
  [--extname=name] [--proto=file] [--skel=dir] [--stubs=file]
  [--no-help] [--xml[=file]] [--full-xml] [--function=proto] [specfile.xml]

  -h|--help          this message
  -f|--force         overwrite existing directories
  -d|--dir           output directory (defaults to extension name)
  -l|--lint          check syntax only, don't create output
  --linespecs        generate #line specs
  -x|--experimental  deprecated
  --function         create a function skeleton from a proto right away
  --version          show version info

  the following options are inherited from ext_skel:
  --extname=module   module is the name of your extension
  --proto=file       file contains prototypes of functions to create
  --xml              generate xml documentation to be added to phpdoc-cvs

  these wait for functionality to be implemented and are ignored for now ...
  --stubs=file       generate only function stubs in file
  --no-help          don't try to be nice and create comments in the code
                     and helper functions to test if the module compiled

  these are accepted for backwards compatibility reasons but not used ...
  --full-xml         generate xml documentation for a self-contained extension
                     (this was also a no-op in ext_skel)
  --skel=dir         path to the skeleton directory
                     (skeleton stuff is now self-contained)
# 

定義ファイル(specファイル)を作成する

モジュール名をfunction_test01(ベタベタやん。。。)とし、以下の2関数を定義してみます。

  • int plus(int x, int y)
    • xとyを加算し、結果を返す
    • オーバーフローは対処してません ;-)
  • string greet([string name])
    • 文字列を受け取り、挨拶文の文字列を返す
    • パラメータが渡されない・NULL・空文字の場合、固定の挨拶文になる

要素名や属性名を見てもらえれば想像が付くと思います。extension要素が最上位の要素となります。function要素で関数名を定義し、その子のproto要素で関数のcode要素で直接Cのコードを書くこともできます。
C言語再入門中のため、ツッコミ歓迎です :-)
また、test要素でテストコードを定義することができます。

<?xml version="1.0" ?>
<extension name="function_test01" version="1.0.0">

 <function name="plus">
  <proto>int plus(int x, int y)</proto>
  <code>
long value;
value = x + y;
RETURN_LONG(value);
  </code>
 </function>

 <function name="greet">
  <proto>string greet([string name])</proto>
  <code>
<![CDATA[
const char *msg = "Hello there !\n";
char *s = NULL;
if (name != NULL && name_len > 0) {
    s = emalloc(name_len + strlen(msg) + 1);
    sprintf(s, "Hello, %s !\n", name);
} else {
    s = msg;
}
RETURN_STRING(s, 1);
efree(s);
]]>
  </code>
 </function>

 <test>
  <code>
   <?data
echo plus(1, 2);
   ?>
  </code>
  <result mode="format">3</result>
 </test>

 <test>
  <code>
   <?data
echo plus(1, -2);
   ?>
  </code>
  <result mode="format">
-1
  </result>
 </test>

 <test>
  <code>
   <?data
echo plus(2147483647, 1);
   ?>
  </code>
  <result mode="format">
   -2147483648
  </result>
 </test>

 <test>
  <code>
   <?data
echo greet('hoge');
   ?>
  </code>
  <result mode="format">
   Hello, hoge !
  </result>
 </test>

 <test>
  <code>
   <?data
echo greet();
   ?>
  </code>
  <result mode="format">
   Hello there !
  </result>
 </test>

 <test>
  <code>
   <?data
echo greet('');
   ?>
  </code>
  <result mode="format">
   Hello there !
  </result>
 </test>

 <test>
  <code>
   <?data
echo greet(null);
   ?>
  </code>
  <result mode="format">
   Hello there !
  </result>
 </test>

</extension>

pecl-genを実行し、ひな形コードを生成する

# pecl-gen -f function_test01.xml
Creating 'function_test01' extension in './function_test01'

Your extension has been created in directory ./function_test01.
See ./function_test01/README and ./function_test01/INSTALL for further instructions.
#

他の拡張モジュールと同様の手順でbuild・インストール

# cd function_test01
# phpize
# ./configure --enable-function-test01
# make install
#

php.iniを編集する

# echo "extension=function_test01.so" >> /path/to/php-cli.ini

テストを実行する

# php ./run-tests.php
=====================================================================
CWD         : /home/shimooka/public_html/codegen_pecl/function_test01
PHP         : /usr/local/lib/php5/bin/php
PHP_SAPI    : cli
PHP_VERSION : 5.2.0RC5
ZEND_VERSION: 2.2.0
PHP_OS      : Linux - Linux ofnir 2.6.9-42.0.3.ELsmp #1 SMP Fri Oct 6 06:21:39 CDT 2006 i686
INI actual  : /usr/local/lib/php5/ini/5.2.0/php-cli.ini
More .INIs  :
Extra dirs  :
=====================================================================
TIME START 2006-10-30 18:15:35
=====================================================================
PASS 001 [tests/001.phpt]
PASS 002 [tests/002.phpt]
PASS 003 [tests/003.phpt]
PASS 004 [tests/004.phpt]
PASS 005 [tests/005.phpt]
PASS 006 [tests/006.phpt]
PASS 007 [tests/007.phpt]
PASS greet() function [tests/greet.phpt]
PASS plus() function [tests/plus.phpt]
=====================================================================
TIME END 2006-10-30 18:15:35

=====================================================================
TEST RESULT SUMMARY
---------------------------------------------------------------------
Exts skipped    :    0
Exts tested     :   30
---------------------------------------------------------------------

Number of tests :    9                 9
Tests skipped   :    0 (  0.0%) --------
Tests warned    :    0 (  0.0%) (  0.0%)
Tests failed    :    0 (  0.0%) (  0.0%)
Tests passed    :    9 (100.0%) (100.0%)
---------------------------------------------------------------------
Time taken      :    0 seconds
=====================================================================

You may have found a problem in PHP.
We would like to send this report automatically to the
PHP QA team, to give us a better understanding of how
the test cases are doing. If you don't want to send it
immediately, you can choose "s" to save the report to
a file that you can send us later.
Do you want to send this report now? [Yns]: n
#

使ってみた感想

ext_skelスクリプトも便利でしたが、これ。。。めちゃくちゃ便利ですね。今回は非常に簡単な関数でしたが、自動生成されたCファイルは全く編集する必要がありませんでした。あと、テストスクリプト(phptファイル)も生成でき、run-tests.phpまで用意されます。
今回は、specファイル(function_test01.xml)のひな形として、cvs.php.netのexamplesにあったspecファイルを使いました。ここには色々なspecファイルの例がありますので、specファイルを書く参考になります。
しかし、何でアーカイブに入ってないんだろ?是非とも入れて欲しいな :-)