swfed extension を作成した時のメモ
準備†
ディレクトリ作成†
$ cd php-x.x.x/ext $ ./ext_skel --extname=swfed $ cd swfed
configure 作成†
- 必要に応じて後でやり直せる (.c ファイルを増やすとか)
$ vi config.m4 PHP_ARG_ENABLE から3行のコメントを外す dnl PHP_ARG_ENABLE(swfed, whether to enable swfed support, dnl Make sure that the comment is aligned: dnl [ --enable-swfed Enable swfed support]) ↑これらの dnl を消す PHP_NEW_EXTENSION に追加するファイルを指定する 前) PHP_NEW_EXTENSION(swfed, swfed.c, $ext_shared) 後) PHP_NEW_EXTENSION(swfed, swfed.c swf_object.c, $ext_shared) ↑空白 $ phpize $ ./configure $ make
クラス実装†
定義 (php_swfed.h)†
- クラスエントリ作成
static zend_class_entry *swfeditor_ce;
- クラスメソッド定義
PHP_METHOD(swfed, __construct); PHP_METHOD(swfed, input);
実装 (swfed.c)†
- ファンクションエントリ作成
zend_function_entry swfed_functions[]= { <略> PHP_ME(swfed, __construct, NULL, 0)
- モジュール初期化でクラス設定
PHP_MINIT_FUNCTION(swfed) <略> zend_class_entry ce; INIT_CLASS_ENTRY(ce, "SWFEditor", swfed_functions); swfeditor_ce = zend_register_internal_class(&ce TSRMLS_CC); le_swfed = zend_register_list_destructors_ex(free_swfed_resource, NULL, "SWFEditor", module_number); zend_declare_property_stringl(swfeditor_ce, "swf_object", strlen("swf_object"), "", 0, ZEND_ACC_PUBLIC);
- ファンクション実装
PHP_METHOD(swfed, __construct) { swf_object_t *swf = swf_object_open(); int ret; ret = zend_list_insert(swf, le_swfed); object_init_ex(getThis(), swfeditor_ce); add_property_resource(getThis(), "swfed", ret); zend_list_addref(ret); }
- クラス内部データも swfed のラベルで保存。
PHP_METHOD(swfed, input) { <略>
オブジェクトに紐づけたデータ処理 (というより Zend に登録したデータの一般的な引き出し方)†
- getThis() で取れる class instance へのポインタを zend_read_properties の第二引数に指定して Zend 管理データから引き出す。
zend_hash_find Z_LVAL_PP zend_list_find
引数の取り方 (string 型)†
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len)
引数の取り方 (可変長引数1)†
- ext/interbase/ibase_blobs.c から引用
switch (ZEND_NUM_ARGS()) { default: WRONG_PARAM_COUNT; case 1: if (FAILURE == zend_parse_parameters(1 TSRMLS_CC, "s", &blob_id, &blob_id_len)) { RETURN_FALSE; } break; case 2: if (FAILURE == zend_parse_parameters(2 TSRMLS_CC, "rs",&link, &blob_id, &blob_id_len)) { RETURN_FALSE; } break; }
引数の取り方 (可変長引数2)†
- zend_get_parameters_array_ex()
- http://manual.xwd.jp/zend.arguments.html
返り値†
- 例
RETURN_{TRUE|FALSE} RETURN_LONG(l) RETURN_STRINGL(s, l, dup)
- 配列の返し方
クラス定数の定義†
- PHP_MINIT_FUNCTION にて以下のように設定。
#define REGISTER_SWFED_CLASS_CONST_LONG(const_name, value) \ zend_declare_class_constant_long(swfeditor_ce, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC); REGISTER_SWFED_CLASS_CONST_LONG("SHAPE_BITMAP_NONE", SWFED_SHAPE_BITMAP_NONE);
警告†
- ext/standard/array.c
php_error_docref(NULL TSRMLS_CC, E_WARNING, "step exceeds the specified range");
例外†
exception の飛ばし方†
zend_throw_exception_ex(zend_exception_get_default(), 1, "Exception at %s:%d", __FILE__, _LINE__);
- 第一引数は zend_class_entry * なので、Exception の継承クラスを作っておけば、好きな Exception を実装して飛ばせそう。
参考†
- PHP拡張モジュールでクラス定義
- メモリ管理
- PHP拡張でクラス実装がよくわからん
- http://www.developer0000.jp/2007/01/07/1310/
○ クラスメソッドはPHP_ME、PHP_METHODを使うらしい。 ○ INIT_CLASS_ENTRY、zend_register_internal_classでクラスを定義。 ○ zend_register_list_destructors_exでデストラクタ時の処理を設定できるらしい。
- http://www.developer0000.jp/2007/01/07/1310/
- C++ で PHP Extension を書く方法 †
- PHP extension からコールバックで hello, world を表示する
- 【PHPext】PHP拡張モジュールの作成
- Writing PHP Extensions - PHP Quebec 2009
本家†
- ZEND DEVELOPER ZONE (Tag: Extension)
- Extension Writing Part II: Parameters, Arrays, and ZVALsの翻訳です。
- php-4.3.7 README.EXT_SKEL 日本語訳 @shoma
- Building Custom PHP Extensions
Klab†
その他†
- PHP extensions workshop
- O'REILLY Programming PHP - 14.8. Returning Values
関連†
- SWF Editor for PHP (swfed)
- PHP/ext/winPHP extension の作り方 (Windows 編)