Do You PHP はてブロ

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

第2回PHP拡張勉強会 - ダイジェスト

GREEさんで開催された第2回PHP拡張勉強会のダイジェストです。なお、http://www.ustream.tv/channel/extstudyUstreamアーカイブを公開中です。id:i_ogiさん、ありがとうございます!

GREE受付
GREE受付 posted by (C)shimooka

PHPマニュアルの読み方(拡張モジュール編)

  • 高木さん!
    • PHPマニュアル・PEARマニュアルのほとんどを翻訳された方です!
  • 情報源
    • 書籍、サイト・・・
    • PHPマニュアルにもあるよ
      • 「Zend Engineハッカーの手引き」
      • まだまだ執筆中
  • オライリーの「プログラミングPHP」第2版にもあるよ
    • books.google.co.jpでタダ読みできる!
    • でも、買ってねw

プログラミングPHP 第2版

プログラミングPHP 第2版

  • 「評価されるの苦手なんで。。。」って、高木さんいい人過ぎる!
    • 「サンプルコードのコメントで遊んでます」w
    • 長く続けるコツは「頑張りすぎない事」
      • あうっ。。。全然手伝えなくてすみません。。。orz

高木さん熱弁中
高木さん熱弁中 posted by (C)shimooka

僕にはtakesakoメソッドは無理だった

  • 関山さん
  • さっき作ったばっかりw
  • zend_module_entry構造体とコールバックについて
  • PHP_MINIT_FUNCTION
    • モジュールのコンストラク
    • 5.2以前はグローバル変数の初期化もしていた
    • 現在は、別のコールバックになっている
      • PHP_GINIT_FUNCTION
      • PHP_GSHUTDOWN_FUNCTION
  • PHP_MSHUTDOWN_FUNCTION
    • モジュールのデストラク
    • ZTSモードであれば、この後プロセスが終了するので破棄しなくてOK
  • PHP_RINIT_FUNCTION
  • PHP_RSHUTDOWN_FUNCTION
  • PHP_MINFO_FUNCTION
  • デモ
    • 「export PROMPT="
    • 簡単なextensionでそれぞれのINIT・SHUTDOWNの呼ばれ方を実演
      • CLICGIでは動作が違う
      • SHUTDOWNされる順番が違うモノがある。RSHUTDOWNは登録順(FIFO)、MSHUTDOWN・GSHUTDOWNは逆順(FILO)
  • Zend拡張
    • 「処理をちょろまかす」
    • フックできる箇所が多い
      • zend_extension構造体
      • zend_extension_entry変数(Zendモジュール用コールバックを定義)
      • →zend_module_entry変数(PHPモジュール用コールバックを定義)
    • ZEND_EXT_APIマクロを定義
    • ZEND_EXTENSIONマクロを呼び出し
    • activate・deactivateはRINIT・RSHUTDOWNに相当
  • CodeGen_PECLが吐くコードは、ZTS非対応なコードを吐いているらしい
  • スレッドセーフではない関数をZTSで使いたい場合
    • TSRM(Winやpthreadのラッパーがある)
    • tsrm_mutex_alloc in GINIT
    • tsrm_mutex_lock / tsrm_mutex_unlock
    • tsrm_mutex_free in GSHUTDOWN

TCC Extensionについて

  • 浜野さん
  • TCC:Tiny C Compiler
    • ライブラリ化:libtcc
  • PHP Extensionを作らずに済む
    • 早いコード
    • ライブラリとリンクできる
    • codepad.orgみたいなのが作れる
  • サンプルコード
  • ダウンロードはhttp://search.cpan.org/~hamano ww
  • なんか、ほとんどできるなぁ
    • 「変態的」by 藤本さん

プレゼン中(浜野さん@KLab)
プレゼン中(浜野さん@KLab) posted by (C)shimooka

ハンズオン

  • 荻原さん
  • 本日のspecファイル
<?xml version="1.0"?>
<!DOCTYPE extension SYSTEM "../extension.dtd">
<extension name="study2">
  <function name="study2_string">
    <proto>string study2_string(string s)</proto>
  </function>
  <function name="study2_int">
    <proto>int study2_int(int i)</proto>
  </function>
  <function name="study2_float">
    <proto>float study2_float(float f)</proto>
  </function>
  <function name="study2_bool">
    <proto>bool study2_bool(bool b)</proto>
  </function>
  <function name="study2_array">
    <proto>array study2_array(array a)</proto>
  </function>
</extension>
  • 最終的なstudy2.php
/*
   +----------------------------------------------------------------------+
   | unknown license:                                                      |
   +----------------------------------------------------------------------+
   | Authors: Unknown User <unknown@example.com>                          |
   +----------------------------------------------------------------------+
*/

/* $ Id: $ */ 

#include "php_study2.h"

#if HAVE_STUDY2

/* {{{ study2_functions[] */
function_entry study2_functions[] = {
	PHP_FE(study2_string        , study2_string_arg_info)
	PHP_FE(study2_int           , study2_int_arg_info)
	PHP_FE(study2_float         , study2_float_arg_info)
	PHP_FE(study2_bool          , study2_bool_arg_info)
	PHP_FE(study2_array         , study2_array_arg_info)
	{ NULL, NULL, NULL }
};
/* }}} */


/* {{{ study2_module_entry
 */
zend_module_entry study2_module_entry = {
	STANDARD_MODULE_HEADER,
	"study2",
	study2_functions,
	PHP_MINIT(study2),     /* Replace with NULL if there is nothing to do at php startup   */ 
	PHP_MSHUTDOWN(study2), /* Replace with NULL if there is nothing to do at php shutdown  */
	PHP_RINIT(study2),     /* Replace with NULL if there is nothing to do at request start */
	PHP_RSHUTDOWN(study2), /* Replace with NULL if there is nothing to do at request end   */
	PHP_MINFO(study2),
	"0.0.1", 
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_STUDY2
ZEND_GET_MODULE(study2)
#endif


/* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(study2)
{

	/* add your stuff here */

	return SUCCESS;
}
/* }}} */


/* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(study2)
{

	/* add your stuff here */

	return SUCCESS;
}
/* }}} */


/* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(study2)
{
	/* add your stuff here */

	return SUCCESS;
}
/* }}} */


/* {{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(study2)
{
	/* add your stuff here */

	return SUCCESS;
}
/* }}} */


/* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(study2)
{
	php_info_print_box_start(0);
	php_printf("<p>The unknown extension</p>\n");
	php_printf("<p>Version 0.0.1devel (2008-03-23)</p>\n");
	php_printf("<p><b>Authors:</b></p>\n");
	php_printf("<p>Unknown User &lt;unknown@example.com&gt; (lead)</p>\n");
	php_info_print_box_end();
	/* add your stuff here */

}
/* }}} */


/* {{{ proto string study2_string(string s)
   */
PHP_FUNCTION(study2_string)
{

	const char * s = NULL;
	int s_len = 0;


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

	RETURN_STRINGL(s, s_len, 1);
}
/* }}} study2_string */


/* {{{ proto int study2_int(int i)
   */
PHP_FUNCTION(study2_int)
{

	long i = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &i) == FAILURE) {
		return;
	}

	RETURN_LONG(i);
}
/* }}} study2_int */


/* {{{ proto float study2_float(float f)
   */
PHP_FUNCTION(study2_float)
{

	double f = 0.0;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &f) == FAILURE) {
		return;
	}

	RETURN_DOUBLE(f);
}
/* }}} study2_float */


/* {{{ proto bool study2_bool(bool b)
   */
PHP_FUNCTION(study2_bool)
{

	zend_bool b = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &b) == FAILURE) {
		return;
	}

	RETURN_BOOL(b);
}
/* }}} study2_bool */


/* {{{ proto array study2_array(array a)
   */
PHP_FUNCTION(study2_array)
{

	zval * a = NULL;
	HashTable * a_hash = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &a) == FAILURE) {
		return;
	}
	a_hash = HASH_OF(a);

	array_init(return_value);
	zend_hash_copy(Z_ARRVAL_P(return_value), a_hash, (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval*));
}
/* }}} study2_array */

#endif /* HAVE_STUDY2 */


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
  • PHPの配列は、内部ではHashTable扱い
  • zval型
    • zval構造体
    • 型、値の共用体、リファレンスの形式、リファレンスカウント
<?php
$a ="abc";
$b = $a;
$b .= "d";  (ここで初めてコピー:CopyOnWrite)
      • Sara女史のphptek 2007のプレゼンを参照のこと
    • zval.value
      • unionとして定義
      • 実際にはマクロ経由でアクセス
      • zend_operators.hに定義

boost php

  • 小泉さん
  • boostみたいに、C++PHP拡張を作る(途中)
  • いきなりデモ
    • コード量がかなり少ない!
  • 内部の話
    • zvalの演算をラッピング
    • php::function
      • テンプレート機能を使って、いろいろな引数を撮る関数を作る
      • さりげなく、藤本さんからサラッと神的発言が。。。スバラシス

予定をちょっとオーバーして終了。今回も濃い勉強会でした。

懇親会は所用のため参加できずorz id:sotarok辺りがまとめてくれていると思うのでw、あとはよしなに。。。