例外を投げるモジュールのCソース
PHP5から例外が使えますが、「例外を投げるモジュール」のCソースはどうなってるのか、ちょっと調べてみました。
結論を先に言うと、以下の2つを書くことになるようです。
- 例外クラス用ポインタの定義(zend_class_entry型のポインタ)
- PHP_MINIT_FUNCTION(モジュール単位の初期化関数)内で例外クラスの初期化(INIT_CLASS_ENTRYマクロ)と登録(zend_register_internal_class/zend_register_internal_class_ex)
PEAR::CodeGen_PECLのspecファイルで書くと以下のような感じです。ExceptionTestクラスのthrowExceptionメソッドを呼び出すと、例外ExceptionTestExceptionを投げてきます。
<?xml version="1.0"?> <extension name="exception_test" version="0.0.1"> <summary>from exception_test</summary> <description>from exception_test</description> <license>PHP</license> <class name="ExceptionTest"> <function name="throwException"> <proto>boolean throwException()</proto> <code> <![CDATA[ zend_throw_exception_ex(exception_test_exception_ce, 0 TSRMLS_CC, "Exception threw"); RETURN_TRUE; ]]> </code> <test> <code> <![CDATA[ try { $obj = new ExceptionTest(); $obj->throwException(); echo 'NG'; } catch (Exception $e) { echo 'OK'; }]]> </code> <result>OK</result> </test> </function> </class> <function role="internal" name="MINIT"> <code> <![CDATA[ zend_class_entry ce; INIT_CLASS_ENTRY(ce, "ExceptionTestException", NULL); exception_test_exception_ce = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC); ]]> </code> </function> </extension>
このExceptionTestExceptionクラス、PHP組み込みのExceptionクラスのサブクラスになっています。確認のためにZend/zend_exceptions.c(PHP5.2.1)を見てみると、以下のようになっていました。
zend_class_entry *default_exception_ce; : ZEND_API zend_class_entry *zend_exception_get_default(TSRMLS_D) /* {{{ */ { return default_exception_ce; } : void zend_register_default_exception(TSRMLS_D) /* {{{ */ { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Exception", default_exception_functions); default_exception_ce = zend_register_internal_class(&ce TSRMLS_CC); : }
Exceptionクラスは基底クラスなのでzend_register_internal_classを使っていますが、ほぼ同じような手順で登録されているのが分かります。