php in ruby

32
PHP in Ruby 2012/09/01 闇 PHP 闇闇闇 do_aki

Upload: doaki

Post on 15-May-2015

2.439 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Php in ruby

PHP in Ruby

2012/09/01 闇 PHP 勉強会

do_aki

Page 2: Php in ruby

@do_aki

http://do-aki.net/

Page 3: Php in ruby

AGENDA

1. 概要 2. 導入 

3. 深部

Page 4: Php in ruby

概要

Page 5: Php in ruby
Page 6: Php in ruby

Ruby on PHP

Page 7: Php in ruby

Ruby on PHP sample (PHP Script)

<?php

ruby_eval(<<<'EOC' def hello_ruby_on_php "HELLO Ruby on PHP!!!" endEOC);

echo ruby_eval('hello_ruby_on_php()');

Page 8: Php in ruby

Ruby on PHP の 構造

php-extension

libruby

php script

Page 9: Php in ruby

反転させてみた

Page 10: Php in ruby

Ruby on PHP の 構造

ruby-extension

libphp5

ruby script

embed

SAPI

Page 11: Php in ruby

php_embed sample (Ruby Script)

# encoding: UTF-8require 'php_embed'

p PhpEmbed.eval('1')p PhpEmbed.eval('true')p PhpEmbed.eval('null')p PhpEmbed.eval('array(1,2,3)')

# 1# true# nil# [1, 2, 3]

Page 12: Php in ruby

導入

Page 13: Php in ruby

Install

1. php-embed SAPI を用意– コンパイル– OS Package (php-embedded / php-

devel)

2. ruby 1.9 環境– 1.8 では動きません– rbenv/ruby-builid が便利

3. gem install php-embed

CentOS6

Page 14: Php in ruby

php-embed SAPI

• ./configure --enable-embed=shared (or static)

• Windows 版もある

• 開発止まってる……?

EXPERIMENTAL

php-build 使ってる場合はPHP_BUILD_CONFIGURE_OPTS=‘--enable-embed’で指定しましょー

Page 15: Php in ruby

ruby 1.9

• OS 標準はだいたい 1.8

• rbenv / ruby-build 使えば導入は簡単– https://github.com/sstephenson/rbenv– https://

github.com/sstephenson/ruby-build

Page 16: Php in ruby

ruby 1.9 構築手順$ cd $ git clone git://github.com/sstephenson/rbenv.git .rbenv$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

# ここで再ログイン

$ mkdir -p ~/.rbenv/plugins$ cd ~/.rbenv/plugins$ git clone git://github.com/sstephenson/ruby-build.git

$ rbenv install 1.9.3-p194

readme に書いてあるけどね

Page 17: Php in ruby

gem install php-embed

• gem : Ruby のパッケージ管理ツール– 1.9 からは標準– rubygems.org– Pure Ruby or C 拡張 関係ないみたい

• bundler で超簡単にライブラリ公開

Page 18: Php in ruby

PHP Programming (in Ruby)

# encoding: UTF-8require 'php_embed'

p PhpEmbed::VERSIONp PhpEmbed.call('phpversion')

p PhpEmbed.call(‘array_intersect’, [1,2,3], [2,3,4]) # [2,3]

Page 19: Php in ruby

深部

Page 20: Php in ruby

php-embed の簡単な使い方#include <sapi/embed/php_embed.h>

int main(int argc, char* argv[]) { PHP_EMBED_START_BLOCK(argc, argv); zend_eval_string( "echo 'Hello Embeded PHP Workd';" , NULL, (char*)"Embeded PHP" TSRMLS_CC );

PHP_EMBED_END_BLOCK();return 0;

}// gcc sample.c –lphp5

Page 21: Php in ruby

zend_eval_stringl

• php code を実行– create_function / preg / ereg で使われてる

• 第3引数 retval_ptr– NULL -> そのまま実行– 非 NULL -> “return” と “ ;” で囲んで実行

• zend_compile_string (= compile_string) – Zend/zend_language_scanner.c

• zend_execute (=dtrace_execute or execute)– Zend/zend_dtrace.c– Zend/zend_vm_execute.h

Page 22: Php in ruby

PHP_EMBED_START(END)_BLOCK

• マクロ• ZTS (Zend Thread Safety) の有無で分

• php_embed_init• try – catch • php_embed_shutdown

Page 23: Php in ruby

PHP_EMBED_*_BLOCK を展開(非ZTS)

int main(int argc, char* argv[]){

php_embed_init(argc, argv);zend_first_try {

zend_eval_string(...)} zend_catch {

} zend_end_try();php_embed_shutdown(TSRMLS_C);

return 0;}

Page 24: Php in ruby

さらに展開

php_embed_init(argc, argv);EG(bailout)=NULL; {

JMP_BUF *__orig_bailout = EG(bailout);JMP_BUF __bailout;

EG(bailout) = &__bailout;if (SETJMP(__bailout)==0) {

zend_eval_string(...)} else {

EG(bailout) = __orig_bailout; }

EG(bailout) = __orig_bailout;}php_embed_shutdown(TSRMLS_C);

Page 25: Php in ruby

出力のハンドリングstatic int php_ub_write(const char *str, unsigned int str_length TSRMLS_DC) { return str_length }

static void php_log_message(char *message) {}

static void php_sapi_error(int type, const char *fmt, ...) {}

php_embed_module.ub_write = php_ub_write;php_embed_module.log_message = php_log_message;php_embed_module.sapi_error = php_sapi_error;

Page 26: Php in ruby

zval と VALUE• zval– php の内部表現– _zval_struct 構造体– = zvalue_value 構造体 + リファレンスカウン

• VALUE– ruby の内部表現– ポインタと同じサイズを持つ unsigned な整数– RVALUE 構造体が実体 (FIXNUM を除いて )

構造体

ポインタ

Page 27: Php in ruby

TYPE(VALUE)

• T_NONE• T_NIL• T_OBJECT• T_CLASS• T_ICLASS• T_MODULE• T_FLOAT• T_STRING• T_REGEXP• T_ARRAY• T_HASH• T_STRUCT• T_BIGNUM

• T_FILE• T_FIXNUM• T_TRUE• T_FALSE• T_DATA• T_MATCH• T_SYMBOL• T_RATIONAL• T_COMPLEX• T_UNDEF• T_NODE• T_ZOMBIE

Page 28: Php in ruby

Z_TYPE (zval)

• IS_NULL• IS_LONG• IS_DOUBLE• IS_BOOL• IS_ARRAY• IS_OBJECT• IS_STRING• IS_RESOURCE• IS_CONSTANT• IS_CONSTANT_ARRAY• IS_CALLABLE

Page 29: Php in ruby

相互変換• それぞれの最終的な内部表現に応じて変

換• いずれも 言語が用意しているマクロや関

数を介して操作

• まだ対応してない型も多い• RESOURCE 型は難しいかもね

Page 30: Php in ruby

嵌ったこと• Ruby 側も、 setjmp / longjmp を使っ

ているらしい• 入れ子状態によってはコアダンプ

Page 31: Php in ruby

最後に• ruby から php のコードを実行できる

ライブラリを作りました

• もうちょいきちんと作り込んで PHP Conference 2012 で発表するつもり

Page 32: Php in ruby

1

Questions?