Ruby Inline

2017-12-14

http://www.zenspider.com/projects/rubyinline.html

chruby の手順で Windows Services for Linux (Windows 10 version 1709) & Ubuntu 16.04 に Ruby 2.4.2 を入れて、試そうとしている。

$ chruby 2.4.2

$ which ruby
/opt/rubies/ruby-2.4.2/bin/ruby

$ ruby -v
ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-linux]

$ gem install -E RubyInline
Fetching: ZenTest-4.11.1.gem (100%)
Successfully installed ZenTest-4.11.1
Fetching: RubyInline-3.12.4.gem (100%)
Successfully installed RubyInline-3.12.4
Parsing documentation for ZenTest-4.11.1
Installing ri documentation for ZenTest-4.11.1
Parsing documentation for RubyInline-3.12.4
Installing ri documentation for RubyInline-3.12.4
Done installing documentation for ZenTest, RubyInline after 1 seconds
2 gems installed
# inline_sample.rb
require "inline"
class MyTest
  inline do |builder|
    builder.c "
      long factorial(int max) {
        int i=max, result=1;
        while (i >= 2) { result *= i--; }
        return result;
      }"
  end
end
t = MyTest.new()
puts t.factorial(10)
$ ruby inline_sample.rb
3628800

いまだに動いている。なんと。

ということはあいかわらず。。

$ pushd ~/.ruby_inline/ruby-2.4.0

$ ls -1
Inline_MyTest_cb89593d1f9fe3ecdb2178215eee80ae.c
Inline_MyTest_cb89593d1f9fe3ecdb2178215eee80ae.c.old
Inline_MyTest_cb89593d1f9fe3ecdb2178215eee80ae.so

$ cat Inline_MyTest_cb89593d1f9fe3ecdb2178215eee80ae.c
#include "ruby.h"

# line 5 "inline_sample.rb"
static VALUE factorial(VALUE self, VALUE _max) {
  int max = FIX2INT(_max);

        int i=max, result=1;
        while (i >= 2) { result *= i--; }
        return LONG2NUM(result);
      }


#ifdef __cplusplus
extern "C" {
#endif
  void Init_Inline_MyTest_cb89593d1f9fe3ecdb2178215eee80ae() {
    VALUE c = rb_cObject;
    c = rb_const_get(c, rb_intern("MyTest"));

    rb_define_method(c, "factorial", (VALUE(*)(ANYARGS))factorial, 1);

  }
#ifdef __cplusplus
}
#endif

$ popd

stdio

# https://github.com/seattlerb/rubyinline/blob/master/demo/hello.rb
begin require 'rubygems' rescue LoadError end
require 'inline'
 
class Hello
  inline do |builder|
    builder.include "<stdio.h>"
    builder.c 'void hello() { puts("hello world"); }'
  end
end
 
Hello.new.hello
$ ruby hello.rb
/home/nishimotz/.gem/ruby/2.4.2/gems/RubyInline-3.12.4/lib/inline.rb:610: warning: Insecure world writable dir /home/nishimotz/.gem/ruby/2.4.2/bin in PATH, mode 040777
hello world

C++

これもほぼサンプルのまま

# inline_cpp_sample.rb
require 'inline'
class MyTest
  inline(:C) do |builder|
    builder.include '<iostream>'
    builder.add_compile_flags '-x c++', '-lstdc++'
    builder.c '
      void hello(int i) {
        while (i-- > 0) {
          std::cout << "hello" << std::endl;
        }
      }'
  end
end
t = MyTest.new()
puts t.hello(3)
$ ruby inline_cpp_sample.rb
/home/nishimotz/.gem/ruby/2.4.2/gems/RubyInline-3.12.4/lib/inline.rb:610: warning: Insecure world writable dir /home/nishimotz/.gem/ruby/2.4.2/bin in PATH, mode 040777
cc1plus: warning: command line option ‘-Wimplicit-int’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wdeclaration-after-statement’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wimplicit-function-declaration’ is valid for C/ObjC but not for C++
cc1plus: warning: unrecognized command line option ‘-Wno-self-assign’
cc1plus: warning: unrecognized command line option ‘-Wno-constant-logical-operand’
cc1plus: warning: unrecognized command line option ‘-Wno-parentheses-equality’
cc1plus: warning: unrecognized command line option ‘-Wno-tautological-compare’
/opt/rubies/ruby-2.4.2/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require': /home/nishimotz/.ruby_inline/ruby-2.4.0/Inline_MyTest_5d41402abc4b2a76b9719d911017c592.so: undefined symbol: _ZSt4cout - /home/nishimotz/.ruby_inline/ruby-2.4.0/Inline_MyTest_5d41402abc4b2a76b9719d911017c592.so (LoadError)
        from /opt/rubies/ruby-2.4.2/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
        from /home/nishimotz/.gem/ruby/2.4.2/gems/RubyInline-3.12.4/lib/inline.rb:523:in `load'
        from /home/nishimotz/.gem/ruby/2.4.2/gems/RubyInline-3.12.4/lib/inline.rb:857:in `inline'
        from inline_cpp_sample.rb:3:in `<class:MyTest>'
        from inline_cpp_sample.rb:2:in `<main>'

おっとエラーになった。

$ nm ~/.ruby_inline/ruby-2.4.0/Inline_MyTest_5d41402abc4b2a76b9719d911017c592.so |grep cout
                 U _ZSt4cout

cout が so の中にないようだ。。

これは動いた:

# inline_cpp_sample2.rb
require 'inline'
class MyTest
  inline(:C) do |builder|
    builder.include '<complex>'
    builder.add_compile_flags '-x c++', '-lstdc++ -lm'
    builder.c '
      double hello(double re, double im) {
        std::complex<double> c(re, im);
        double a = std::abs(c);
        return a;
      }'
  end
end
t = MyTest.new()
puts t.hello(3, 5)
$ ruby inline_cpp_sample2.rb
/home/nishimotz/.gem/ruby/2.4.2/gems/RubyInline-3.12.4/lib/inline.rb:610: warning: Insecure world writable dir /home/nishimotz/.gem/ruby/2.4.2/bin in PATH, mode 040777
cc1plus: warning: command line option ‘-Wimplicit-int’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wdeclaration-after-statement’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wimplicit-function-declaration’ is valid for C/ObjC but not for C++
cc1plus: warning: unrecognized command line option ‘-Wno-self-assign’
cc1plus: warning: unrecognized command line option ‘-Wno-constant-logical-operand’
cc1plus: warning: unrecognized command line option ‘-Wno-parentheses-equality’
cc1plus: warning: unrecognized command line option ‘-Wno-tautological-compare’
5.830951894845301

C++11

うごいた

# inline_cpp_sample3.rb
require 'inline'
class MyTest
  inline(:C) do |builder|
    builder.include '<complex>'
    builder.add_compile_flags '-x c++', '-lstdc++ -lm', '-std=c++11'
    builder.c '
      double hello(double re, double im) {
        std::complex<double> c(re, im);
        auto a = std::abs(c);
        return a;
      }'
  end
end
t = MyTest.new()
puts t.hello(3, 5)
$ ruby inline_cpp_sample3.rb
/home/nishimotz/.gem/ruby/2.4.2/gems/RubyInline-3.12.4/lib/inline.rb:610: warning: Insecure world writable dir /home/nishimotz/.gem/ruby/2.4.2/bin in PATH, mode 040777
cc1plus: warning: command line option ‘-Wimplicit-int’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wdeclaration-after-statement’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wimplicit-function-declaration’ is valid for C/ObjC but not for C++
cc1plus: warning: unrecognized command line option ‘-Wno-self-assign’
cc1plus: warning: unrecognized command line option ‘-Wno-constant-logical-operand’
cc1plus: warning: unrecognized command line option ‘-Wno-parentheses-equality’
cc1plus: warning: unrecognized command line option ‘-Wno-tautological-compare’
5.830951894845301

Ruby Inline (2009)

以下、2009年11月ごろ書いた記事

ruby プログラムに C 言語のコードを埋め込むための機能拡張。

基本

http://rubyinline.rubyforge.org/RubyInline/

$ sudo gem install RubyInline
[sudo] password for nishi: 
Successfully installed ZenTest-4.1.3
Successfully installed RubyInline-3.8.2
2 gems installed
Installing ri documentation for ZenTest-4.1.3...
Installing ri documentation for RubyInline-3.8.2...
Installing RDoc documentation for ZenTest-4.1.3...
Installing RDoc documentation for RubyInline-3.8.2...

http://blog.tkmr.org/tatsuya/show/299-ruby-c-rubyinline

に書かれているサンプルを実行するが、

inline_sample.rb:32: undefined method `plus_inline' for #<Test:0xb7bcf428> (NoMethodError)

になる。

気を取り直して gems に入っている example を実行したら動いた!

$ cp /usr/lib/ruby/gems/1.8/gems/RubyInline-3.8.2/example.rb .
$ ruby example.rb 
# of iterations = 1000000, n = 5
                          user     system      total        real
null_time             1.310000   0.920000   2.230000 (  2.621937)
c                     5.040000   2.790000   7.830000 ( 10.498556)
c-raw                 5.240000   2.560000   7.800000 (  8.104351)
c-alias               5.100000   2.700000   7.800000 (  8.025086)
pure ruby            20.700000  12.360000  33.060000 ( 35.544498)

関数名によって動かなくなるらしい。

動かない場合:

#!/usr/bin/ruby
require 'rubygems'
require 'inline'
class Test
  inline do |builder|
    builder.c "
      int plus_inline(int x, int y){
        return x + y;
      }
    "
  end
end
p Test.new.plus_inline(1,1)
$ ruby inline_sample.rb
inline_sample.rb:13: undefined method `plus_inline' for #<Test:0xb7b9f124> (NoMethodError)

動く場合

#!/usr/bin/ruby
require 'rubygems'
require 'inline'
class Test
  inline do |builder|
    builder.c "
      int add(int x, int y){
        return x + y;
      }
    "
  end
end
p Test.new.add(1,1)
$ ruby inline_sample.rb
2

-d オプション付きで実行するといろいろ警告が出ているが、これでいいらしい。

$ ruby -d inline_sample.rb
Exception `LoadError' at /usr/local/lib/site_ruby/1.8/rubygems.rb:1113 - no such file to load -- rubygems/defaults/operating_system
Exception `NoMethodError' at /usr/lib/ruby/1.8/rational.rb:78 - undefined method `gcd' for Rational(1, 2):Rational
Exception `LoadError' at /usr/local/lib/site_ruby/1.8/rubygems/config_file.rb:34 - no such file to load -- Win32API
Exception `LoadError' at /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31 - no such file to load -- inline
RubyInline v 3.8.2
Exception `LoadError' at /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31 - no such file to load -- inline/Inline_Test_34ec.so
Exception `LoadError' at /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:38 - no such file to load -- inline/Inline_Test_34ec.so
/home/nishi/.ruby_inline/Inline_Test_34ec.so is up to date
2

heroku における inline

ちゃんとherokuで使えるということがわかった。

$ ./script/generate scaffold item name:string
$ echo "RubyInline" >> .gems

items_controller.rb

require 'inline'
 
class Test
  inline do |builder|
    builder.c "
      int add(int x, int y) {
        return x + y;
      }
    "
  end
end
 
class ItemsController < ApplicationController
  # GET /items
  # GET /items.xml
  def index
    @items = Item.all
    @test = Test.new.add(1, 1)
以下略

items/index.html.erb

<h1>Listing items</h1>
<p> test = <%= @test %> </p>
以下略

のようなものが git push heroku master; heroku db:migrate して http://app-name.heroku.com/items/ で動いた。

ruby_inline.txt · 最終更新: 2017/12/14 17:45 by Takuya Nishimoto
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0