a bridge between php and ruby
DESCRIPTION
2013/01/13 Tokyo Ruby Kaigi 10TRANSCRIPT
PHP と
Ruby の
架け橋 2013/01/13
Tokyo Ruby Kaigi 10
do_aki
@do_aki
http://do-aki.net/
About 2 extensions
php-extension ruby Runnable ruby script in PHP (>=5.4)
php_embed gem library Runnable php script in Ruby(>= 1.9)
https://github.com/do-aki/php-ext-ruby
php-ext-ruby sample code <?php
// php.ini : extension=ruby.so
ruby_eval(<<<'EOS'
def hello
“Ruby #{RUBY_VERSION} in PHP! "
end
EOS
);
echo ruby_eval('hello()'); # Ruby 1.9.3 in PHP!
Web Application?
sinatra on ext-ruby <?php
// php.ini : extension=ruby.so
ruby_require(‘sinatra’);
ruby_eval(<<<EOS
get ‘/’
‘Hello sinatra in PHP!’
end
EOS
);
sinatra on ext-ruby (not work)
<?php
// php.ini : extension=ruby.so
ruby_require(‘sinatra’);
ruby_eval(<<<EOS
get ‘/’
‘Hello sinatra in PHP!’
end
EOS
);
ruby_require calls rb_require but…
• rb_require is ‘require’ in Ruby script
• require is not rb_require in Ruby 1.9
• rb_require(“rubygems”) already called
• rubygems override original require!
• also not work (another reason) rb_funcall(rb_mKernel, rb_intern(“require”)) ?
sinatra on ext-ruby again <?php
ruby_eval(<<<EOS
require 'sinatra/base‘
class App < Sinatra::Base
get '/' do
'Hello Sinatra in PHP!'
end
end
EOS
);
突然の死 (Segmentation fault)
次回作にご期待ください
• Runnable standard library
• ruby-mysql library runs too
• Web application works in PHP and Ruby if you make F/W which runnable on this extension!
o...rz
<?php
ruby_eval(<<<'EOC'
require 'mysql'
client = Mysql.connect('127.0.0.1', ‘usr', ‘pas’, 'test')
client.query("SELECT id,name FROM hoge").each do |id, name|
p [id, name]
end
EOC
);
php_embed (rubygems.org)
https://rubygems.org/gems/php_embed
php_embed sample code require ‘php_embed’
PhpEmbed.eval <<EOS
function hello($rv) {
$pv = phpversion();
return “PHP {$pv} in Ruby {$rv}!”;
}
EOS
retval = PhpEmbed.call(:hello, RUBY_VERSION)
p retval # PHP 5.4.10 in Ruby 1.9.3!
PhpEmbed::Value Class
• This class holds a PHP variable
• Convert Ruby variables into PHP variables (new)
• Convert PHP variables into Ruby variables (to_X)
• PHPnized comparison rule
PhpEmbed::Value sample code p_ary = PhpEmbed::Value.new([1, 2, 3])
p p_ary # Array
p p_ary.to_a # [1, 2, 3]
p p_ary.to_a[0].class # PhpEmbed::Value
---------------------------------------------------------
p_zero = PhpEmbed::Value.new(0)
p_false = PhpEmbed::Value.new(false)
p pzero == p_false # true
PhpEmbed::Value sample code func = PhpEmbed::Value.eval << EOS
function ($ary) {
return count($ary);
}
EOS
p func.class # PhpEmbed::Value
p func.callable? # true
p func.call(1..100); # 100
Web Application?
sorry……
PHP Architecture
Web Server
or
OS SAPI
Zend Engine
Extensions
PHP Script
PHP SAPIs
aolserver / apache / apache2filter /
apache2handler / apache_hooks /
caudium / cgi / cli / continuity / embed
/ fpm / isapi / litespeed / milter / nsapi
/ phttpd / pi3web / roxen / thttpd / tux
/ webjames under sapi directory in php-5.4.10 source code
PHP SAPIs
aolserver / apache / apache2filter /
apache2handler / apache_hooks /
caudium / cgi / cli / continuity / embed
/ fpm / isapi / litespeed / milter / nsapi
/ phttpd / pi3web / roxen / thttpd / tux
/ webjames under sapi directory in php-5.4.10 source code
php_embed uses embed SAPI . But embed SAPI has not interface to web server
PHP Installer
• gem install php_embed
– require “libphp5”
– yum install php-embedded php-devel
– Or compile php yourself
• gem install php_embed -- --compile-php
– compile minimal php (in gem directory)
– require gcc / tar / make
php-extension ruby Runnable ruby script in PHP (>=5.4)
php_embed gem library Runnable php script in Ruby(>= 1.9)
Just for Fun
Difference between PHP and Ruby
in extensions
Overview of PHP/Ruby extension
• Written by C language mostly
• Method(Function) in Ruby/PHP calls C Function
PHP
Ruby
Extension (C Function)
PHP
Ruby
retrun value
args
Overview of PHP/Ruby extension
PHP
Ruby
Extension (C Function)
PHP
Ruby
zval VALUE
zval VALUE
VALUE internal representation of
variable in Ruby
zval internal representation of
variable in PHP
zval VS VALUE zval
type info
+ reference count
+ value
lval (integer)
dval (floating point)
str (string)
ht (hash table)
obj (object)
VALUE
pointer (*RVALUE)
RBasic / RObject / RClass /
RFloat / RString / RArray / RRegexp / RHash … and others
or value
– false / true / nil / symbol
– same integer
– some float (>= 2.0?)
Simple Complex
Garbage Collection
zval
reference counting
+ circular reference collector
VALUE
mark and sweep (conservative)
easy handling difficulty handling
zend_eval_string (PHP) define:
ZEND_API int zend_eval_string(
char *str, zval *retval_ptr, char *string_name
TSRMLS_DC);
example:
char *code = “$value=1”, *name=“value”;
zval ret;
zend_eval_string(code, &ret, name TSRMLS_CC);
rb_eval_string (Ruby)
define:
VALUE rb_eval_string(const char *str);
example:
char *code = “value=1”;
VALUE ret;
ret = rb_eval_string(code);
Build extensions
PHP
m4 macros
autoconf
Ruby
Ruby script
mkmf library
$ phpize $ configure $ make $ make install
$ ruby extconf.rb $ make $ make install
Code Reading
GNU Global (htags) http://www.gnu.org/software/global/
cgdb http://cgdb.github.com/
References
Ruby:
RHG (Rubyソースコード完全解説)
http://i.loveruby.net/ja/rhg/
PHP :
php.net
PHP Extension Writing (PHP Quebec 2009)
http://talks.somabo.de/200903_montreal_php_extension_writing.pdf
Notice: they are old a little
Commit log
Conclusion
処理系/拡張 いじるの
めっさ楽しい!
Thank you!
英語間違えてたらこっそり教えて><
2013/01/13 Tokyo Ruby Kaigi 10 A Bridge Between PHP and Ruby
@do_aki