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?
<?php
       sinatra on ext-ruby
// php.ini : extension=ruby.so
ruby_require(‘sinatra’);
ruby_eval(<<<EOS
     get ‘/’
             ‘Hello sinatra in PHP!’
     end
EOS
);
sinatra on ext-ruby
<?php                                  (not
                       work)
// 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
require ‘php_embed’
    php_embed sample code
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
p_ary = PhpEmbed::Value.new([1, 2, 3])
  PhpEmbed::Value sample code
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
func = PhpEmbed::Value.evalsample
  PhpEmbed::Value            << EOS   code
     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

                     PHP Script
                 Extensions
 Web
Server
  or
                         Zend
              SAPI
 OS                     Engine
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 /
        php_embed uses embed SAPI .
          But embed SAPI has not
apache2handler /web server
           interface to 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 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

                    Extension
                   (C Function)
PHP                                          PHP
                                  retrun
        args
                                   value
Ruby                                         Ruby



 • Written by C language mostly
 • Method(Function) in Ruby/PHP calls C Function
Overview of PHP/Ruby extension

                          Extension
                         (C Function)
PHP                                                       PHP
         zval                             zval
        VALUE                            VALUE
Ruby                                                      Ruby



            zval                          VALUE
   internal representation of     internal representation of
        variable in PHP                variable in Ruby
zval           zval VSVALUE
                       VALUE
type info                  pointer (*RVALUE)
 + reference count            RBasic / RObject / RClass /
 + value                   RFloat / RString / RArray /
                           RRegexp / RHash … and others
   lval (integer)
   dval (floating point)   or value
   str (string)               – false / true / nil / symbol
   ht (hash table)            – same integer
                              – some float (>= 2.0?)
   obj (object)

               Simple                      Complex
Garbage Collection
zval                     VALUE

  reference counting        mark and sweep
  + circular reference       (conservative)
        collector



   difficulty handling       easy 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                 Ruby

 $ phpize            $ ruby extconf.rb
 $ configure         $ make
 $ make              $ make install
 $ make install

m4 macros           Ruby script
autoconf            mkmf library
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
英語間違えてたらこっそり教えて><

A bridge between php and ruby

  • 1.
    PHP と Ruby の 架け橋 2013/01/13 Tokyo Ruby Kaigi 10 do_aki
  • 2.
  • 3.
    About 2 extensions php-extension ruby Runnable ruby script in PHP (>=5.4) php_embed gem library Runnable php script in Ruby(>= 1.9)
  • 4.
  • 6.
    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!
  • 7.
  • 8.
    <?php sinatra on ext-ruby // php.ini : extension=ruby.so ruby_require(‘sinatra’); ruby_eval(<<<EOS get ‘/’ ‘Hello sinatra in PHP!’ end EOS );
  • 9.
    sinatra on ext-ruby <?php (not work) // php.ini : extension=ruby.so ruby_require(‘sinatra’); ruby_eval(<<<EOS get ‘/’ ‘Hello sinatra in PHP!’ end EOS );
  • 10.
    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”)) ?
  • 11.
    sinatra on ext-rubyagain <?php ruby_eval(<<<EOS require 'sinatra/base‘ class App < Sinatra::Base get '/' do 'Hello Sinatra in PHP!' end end EOS );
  • 12.
  • 13.
    次回作にご期待ください • Runnable standardlibrary • ruby-mysql library runs too • Web application works in PHP and Ruby if you make F/W which runnable on this extension! o...rz
  • 14.
    <?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 );
  • 15.
    php_embed (rubygems.org) https://rubygems.org/gems/php_embed
  • 16.
    require ‘php_embed’ php_embed sample code 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!
  • 17.
    PhpEmbed::Value Class • Thisclass holds a PHP variable • Convert Ruby variables into PHP variables (new) • Convert PHP variables into Ruby variables (to_X) • PHPnized comparison rule
  • 18.
    p_ary = PhpEmbed::Value.new([1,2, 3]) PhpEmbed::Value sample code 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
  • 19.
    func = PhpEmbed::Value.evalsample PhpEmbed::Value << EOS code function ($ary) { return count($ary); } EOS p func.class # PhpEmbed::Value p func.callable? # true p func.call(1..100); # 100
  • 20.
  • 21.
  • 22.
    PHP Architecture PHP Script Extensions Web Server or Zend SAPI OS Engine
  • 23.
    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
  • 24.
    PHP SAPIs aolserver /apache / apache2filter / php_embed uses embed SAPI . But embed SAPI has not apache2handler /web server interface to 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
  • 25.
    PHP Installer • geminstall 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
  • 27.
    php-extension ruby Runnable rubyscript in PHP (>=5.4) php_embed gem library Runnable php script in Ruby(>= 1.9)
  • 28.
  • 29.
    Difference between PHP and Ruby in extensions
  • 30.
    Overview of PHP/Rubyextension Extension (C Function) PHP PHP retrun args value Ruby Ruby • Written by C language mostly • Method(Function) in Ruby/PHP calls C Function
  • 31.
    Overview of PHP/Rubyextension Extension (C Function) PHP PHP zval zval VALUE VALUE Ruby Ruby zval VALUE internal representation of internal representation of variable in PHP variable in Ruby
  • 32.
    zval zval VSVALUE VALUE type info pointer (*RVALUE) + reference count RBasic / RObject / RClass / + value RFloat / RString / RArray / RRegexp / RHash … and others lval (integer) dval (floating point) or value str (string) – false / true / nil / symbol ht (hash table) – same integer – some float (>= 2.0?) obj (object) Simple Complex
  • 33.
    Garbage Collection zval VALUE reference counting mark and sweep + circular reference (conservative) collector difficulty handling easy handling
  • 34.
    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);
  • 35.
    rb_eval_string (Ruby) define: VALUE rb_eval_string(const char *str); example: char *code = “value=1”; VALUE ret; ret = rb_eval_string(code);
  • 36.
    Build extensions PHP Ruby $ phpize $ ruby extconf.rb $ configure $ make $ make $ make install $ make install m4 macros Ruby script autoconf mkmf library
  • 37.
  • 38.
    GNU Global (htags) http://www.gnu.org/software/global/
  • 39.
  • 40.
    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
  • 41.
  • 42.
    Conclusion 処理系/拡張 いじるの めっさ楽しい!
  • 43.
    Thank you! 2013/01/13 Tokyo Ruby Kaigi 10 A Bridge Between PHP and Ruby @do_aki 英語間違えてたらこっそり教えて><