IiP - Io in PHP

php_iovm-070920.tgz


ちょーシンプルなIoバインディング。息抜きがてらにさくっと作ってみました。
IoStateオブジェクトと、引数として与えられたコードを実行するdoCStringメソッドだけしかありません。
本格的に作り込む時間がないので、しばらくはこのまま放置です。


configureでは --with-iovm でIoのインストール先ディレクトリを、--with-iosource でIoのソースコードがあるディレクトリを指定します。

phpize
./configure --with-iovm=/opt/io --with-iosource=/work/Io-2007-05-28
make
sudo make install


こんなふうに使います。IoObject<->zvalのブリッジは作っていませんが、IoState内でスロットに代入されたオブジェクトは生き続けます。

<?php
$io = new IoState();
$io->doCString("writeln(\"Hello, World!\")");
$io->doCString("hw := \"Hello, World!\"");
$io->doCString("writeln(hw)");
?>


同名のシンボルでもIoStateごとに独立です。ZendEngineのようにグローバル変数に状態を持っていないあたりにIoの設計の良さの一端が見えますね。

<?php
$io1 = new IoState();
$io2 = new IoState();
$io1->doCString("sym := \"state1\"");
$io2->doCString("sym := \"state2\"");
$io1->doCString("writeln(sym)");
$io2->doCString("writeln(sym)");
?>


デストラクタをコールした後doCStringしようとすると例外を投げます。(ふつうはこんなことしませんが)

<?php
$io->__destruct();
$io->doCString("writeln(\"may broken\")");
?>


独自のオブジェクト構造体とそのハンドラを定義するのが面倒だったのでIoStateのポインタをlongにキャストしてprivateなプロパティに持っています。

static void class_init_IoState(TSRMLS_D)
{
	zend_class_entry ce;

	INIT_CLASS_ENTRY(ce, "IoState", IoState_methods);
	ce_IoState = zend_register_internal_class(&ce);
	zend_declare_property_null(ce_IoState, "state", 5, ZEND_ACC_PRIVATE TSRMLS_CC);
}
PHP_METHOD(IoState, __construct)
{
	IoState *stat = IoState_new();
	zend_update_property_long(ce_IoState, getThis(), "state", 5, (long)stat TSRMLS_CC);
}
PHP_METHOD(IoState, doCString)
{
	const char *code = NULL;
	int code_len = 0;
	long stat;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &code, &code_len) == FAILURE) {
		return;
	}

	stat = Z_LVAL_P(zend_read_property(ce_IoState, getThis(), "state", 5, 1 TSRMLS_CC));
	if (stat == 0) {
		zend_throw_exception(zend_exception_get_default(), "IoState broken", 0 TSRMLS_CC);
		return;
	}
	IoState_doCString_((IoState *)stat, code);
}
PHP_METHOD(IoState, __destruct)
{
	long stat = Z_LVAL_P(zend_read_property(ce_IoState, getThis(), "state", 5, 1 TSRMLS_CC));
	if (stat == 0) {
		zend_throw_exception(zend_exception_get_default(), "IoState broken", 0 TSRMLS_CC);
		return;
	}
	IoState_free((IoState *)stat);
	zend_update_property_long(ce_IoState, getThis(), "state", 5, 0 TSRMLS_CC);
}


そんなわけでLLP64のようなポインタの大きさとlongの大きさが異なる環境では動きません。

static PHP_MINIT_FUNCTION(iovm)
{
	if (sizeof(long) != sizeof(IoState *)) {
		php_error(E_ERROR, "IoVM extension cannot work on this machine");
		return FAILURE;
	}

	class_init_IoState(TSRMLS_C);

	return SUCCESS;
}