Mozo.PHP (その3)
今日の最初の方にリリースしたものはメモリリークします。
本気で使っている方はここから最新版を再度落としてください。
エラー処理 (1)
C++ の関数からエラーを出して呼び出し元に復帰したいときは、mozo::php::runtime_error を throw します。
throw php::runtime_error("something went wrong!");
これだけです。
エラー処理 (2) -- MOZO_PHP_BEGIN_CAPTURE_ERROR / MOZO_PHP_END_CAPTURE_ERROR / MOZO_PHP_LAST_ERROR
mozo::php::function で PHP の関数を C++ から呼び出したときに、track_errors=1 みたく関数のエラーメッセージをキャプチャしたい場合があります。このとき便利なのが MOZO_PHP_BEGIN_CAPTURE_ERROR、 MOZO_PHP_END_CAPTURE_ERROR と MOZO_PHP_LAST_ERROR というマクロです。
まずは、エラーをキャプチャしたいステートメントを MOZO_PHP_BEGIN_CAPTURE_ERROR と MOZO_PHP_END_CAPTURE_ERROR で囲みます。そのブロック内でエラーメッセージが出力されたら、mozo::php::error_info クラスの参照である MOZO_PHP_LAST_ERROR から、エラーの発生したファイル名、行番号とエラーメッセージの情報を取得することができます。
もしエラーメッセージが一切出力されなかった場合に MOZO_PHP_LAST_ERROR を参照すると、すべての要素が空となっています。エラーメッセージが実際に出力されたかどうかは。mozo::php::error_info::valid() メソッドの戻り値で確認できます。
MOZO_PHP_BEGIN_CAPTURE_ERROR // php_function がエラーを返した if (*php_function() == false) { const php::error_info& error(MOZO_PHP_LAST_ERROR); std::cout << error.filename() << std::endl; std::cout << error.line_number() << std::endl; std::cout << error.message() << std::endl; } MOZO_PHP_END_CAPTURE_ERROR
以下に、file_get_contents() を実装した例を示します。
#include "mozo/php/module.hpp" #include "mozo/php/function.hpp" using namespace mozo; class m006_module : public php::module, public php::function_container<m006_module> { public: class handler : public php::module::handler { public: handler(m006_module* mod) :php::module::handler(mod) {} static php::value_ptr my_file_get_contents(::std::string filename) { php::function fopen("fopen"), fread("fread"), filesize("filesize"), fclose("fclose"); php::value_ptr $fp, $retval; MOZO_PHP_BEGIN_CAPTURE_ERROR $fp = fopen(filename, "rb"); if (*$fp == false) { throw php::runtime_error( std::string("Failure in system function: \"") + MOZO_PHP_LAST_ERROR.message() + "\"", MOZO_PHP_LAST_ERROR.filename().c_str(), MOZO_PHP_LAST_ERROR.line_number()); } MOZO_PHP_END_CAPTURE_ERROR try { MOZO_PHP_BEGIN_CAPTURE_ERROR $retval = fread($fp, filesize(filename)); if (*$retval == false) { throw php::runtime_error( std::string("Failure in system function: \"") + MOZO_PHP_LAST_ERROR.message() + "\"", MOZO_PHP_LAST_ERROR.filename().c_str(), MOZO_PHP_LAST_ERROR.line_number()); } MOZO_PHP_END_CAPTURE_ERROR } catch (const ::std::exception&) { fclose($fp); throw; } // finally がほしい... fclose($fp); return $retval; } }; public: m006_module(zend_module_entry* entry) : php::module(entry) { entry->functions = defun("my_file_get_contents", &handler::my_file_get_contents); } }; #define MOZO_PHP_MODULE_NAME m006 #define MOZO_PHP_MODULE_CAPITALIZED_NAME M006 #define MOZO_PHP_MODULE_VERSION "0.1" #define MOZO_PHP_MODULE_CLASS_NAME m006_module #include "mozo/php/module_def.hpp"