Ruby Interface of Erlang

Discussion in 'Ruby' started by KDr2, Apr 27, 2009.

  1. KDr2

    KDr2 Guest

    [Note: parts of this message were removed to make it a legal post.]

    Hello, erveyone,I just start a new project called erlix,the ruby interface
    for erlang,at http://code.google.com/p/erlix ,you may need it.

    Erlix can help you communicating with the erlang-node, you can write
    distributed programs with ruby and erlang easily.

    Just read its api docs if you need it.
     
    KDr2, Apr 27, 2009
    #1
    1. Advertisements

  2. How does this compare to Erlectricity?

    http://code.google.com/p/erlectricity
     
    David Masover, Apr 27, 2009
    #2
    1. Advertisements

  3. KDr2

    KDr2 Guest

    [Note: parts of this message were removed to make it a legal post.]

    1.Erlectricity interact with Erlang through the ports system. If you are an
    Erlang programmer,you will feel confused about it:
    Where are my Erlang-Terms? How to match two Terms? How to make my
    ruby-process an erlang-node? so i start the project erlix.
    2.erlix is based on the erl_interface, all its api is the same as
    erl_interface:

    irb(main):001:0> require "erlix"
    => true
    irb(main):002:0>
    list=ErlixList.new([ErlixAtom.new("erlatom"),ErlixInt.new(2),ErlixFloat.new(3.0)])
    => #<ErlixList:0xb7c738e8>
    irb(main):003:0> list.puts
    [erlatom,2,3.000000]
    => nil
    irb(main):004:0> list.match("[A,2,B]")
    => true
    irb(main):005:0> list.match("[A,3,B]")
    => false
    irb(main):006:0> b=list.mget("[Atom,_,_]","Atom")
    => erlatom
    irb(main):007:0> b.class
    => ErlixAtom
    irb(main):008:0> ObjectSpace.each_object(Class).inject([]){|a,i|a<< i if
    i.ancestors.any?{|k|k==ErlixTerm};a}
    => [ErlixBinary, ErlixTuple, ErlixList, ErlixAtom, ErlixRef, ErlixPid,
    ErlixFloat, ErlixUInt, ErlixInt]
    irb(main):009:0>

    And... use erlix, you can make you ruby-process an Erlang-Node(read the test
    code in the src-package) hehe

    :)
     
    KDr2, Apr 28, 2009
    #3
  4. KDr2

    KDr2 Guest

    [Note: parts of this message were removed to make it a legal post.]

    I release erlix-v0.3 today:

    bugfix:

    IO block bug in
    ErlixConnection?<http://code.google.com/p/erlix/w/edit/ErlixConnection>#erecv


    feature:

    1. ErlixList?
    <http://code.google.com/p/erlix/w/edit/ErlixList>#new("string")

    2. ErlixConnection?<http://code.google.com/p/erlix/w/edit/ErlixConnection>#close

    3. ErlixConnection?<http://code.google.com/p/erlix/w/edit/ErlixConnection>#closed?

    4. ErlixConnection?<http://code.google.com/p/erlix/w/edit/ErlixConnection>
    #rpc("module","function",ErlixTermList?<http://code.google.com/p/erlix/w/edit/ErlixTermList>)

    5. ErlixConnection?<http://code.google.com/p/erlix/w/edit/ErlixConnection>#peer


    see the section Erlix RPC on
    http://code.google.com/p/erlix/wiki/ErlixTutorial


     
    KDr2, Apr 29, 2009
    #4
  5. Just a thought: if you were to move all these constants into an Erlix
    module (e.g. Erlix::Tuple, Erlix::Int etc) then you could 'include
    Erlix' and save a lot of typing. The only conflict I can see would be
    Float, and you can always use ::Float to get the Ruby one should you
    need it.

    The separate namespace can also be useful when creating objects
    dynamically:
    type = "Tuple"
    obj = Erlix.const_get(type).new

    You could also consider module functions as a shortcut for constructors.

    module Erlix
    # Fake implementation
    class Tuple
    def initialize(*x)
    @data = *x
    end
    end
    class Int
    def initialize(x)
    @data = x
    end
    end

    # Module functions
    def Tuple(*x)
    Tuple.new(*x)
    end
    module_function :Tuple
    def Int(*x)
    Int.new(*x)
    end
    module_function :Int
    # etc
    end

    include Erlix
    puts Tuple(Tuple(Int(1)), Int(2)).inspect

    Regards,

    Brian.
     
    Brian Candler, Apr 29, 2009
    #5
  6. KDr2

    KDr2 Guest

    [Note: parts of this message were removed to make it a legal post.]

    Thank you for your advise :) They are very useful for me.
     
    KDr2, Apr 29, 2009
    #6
  7. BTW, I haven't been able to get it to build yet - it's stuck looking for
    -lei

    $ ruby configure.rb
    --with-ei-dir=/usr/lib/erlang/lib/erl_interface-3.5.7
    *** ./extconf.rb failed ***
    Could not create Makefile due to some reason, probably lack of
    necessary libraries and/or headers. Check the mkmf.log file for more
    details. You may need configuration options.

    Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/usr/local/bin/ruby
    --with-ei-dir
    --with-ei-include
    --without-ei-include=${ei-dir}/include
    --with-ei-lib
    --without-ei-lib=${ei-dir}/lib
    --with-eilib
    --without-eilib
    checking for erl_init() in -lei... no
    error: erl_interface not found!
    $ ls /usr/lib/erlang/lib/erl_interface-3.5.7/
    bin doc include info lib src
    $

    I've tried various values for --with-eir without success. This is under
    Ubuntu Hardy but with erlang 12.b.3 from Intrepid. (Works fine with
    CouchDB, for example).

    On a different point, I noticed the following in the C source:

    //check: all elements' must be ErlixTerm
    for(i=0;i<RARRAY(array)->len;i++){
    VALUE e=RARRAY(array)->ptr;
    if(!IS_ETERM(e)){
    rb_raise(rb_eTypeError,"all tuple's elements must be ErlixTerm!");
    }
    }

    I think it could be useful if some automatic conversions were done here.
    e.g. Fixnum converted to Erlix[::]Int automatically, String to a List,
    maybe Array to Tuple. However maybe they're done elsewhere - as I say,
    I've not been able to run it yet.

    Regards,

    Brian.
     
    Brian Candler, Apr 29, 2009
    #7
  8. I found the problem. In configure.rb I had to add "-pthread" to
    --with-ldflags. Without that, mkmf.log was showing the following errors:

    "gcc -o conftest -I. -I/usr/local/lib/ruby/1.8/i686-linux -I./src
    -I/usr/lib/erlang/lib/erl_interface-3.5.7/include -g -O2 conftest.c
    -L'.' -L'/usr/local/lib' -Wl,-R'/usr/local/lib'
    -L'/usr/lib/erlang/lib/erl_interface-3.5.7/lib'
    -Wl,-R'/usr/lib/erlang/lib/erl_interface-3.5.7/lib' -lei -lerl_interface
    -lruby-static -lei -ldl -lcrypt -lm -lc"
    /usr/lib/erlang/lib/erl_interface-3.5.7/lib/libei.a(ei_pthreads.o): In
    function `__erl_errno_place':
    (.text+0x4c): undefined reference to `pthread_once'
    /usr/lib/erlang/lib/erl_interface-3.5.7/lib/libei.a(ei_pthreads.o): In
    function `__erl_errno_place':
    (.text+0x7a): undefined reference to `pthread_getspecific'
    /usr/lib/erlang/lib/erl_interface-3.5.7/lib/libei.a(ei_pthreads.o): In
    function `__erl_errno_place':
    (.text+0xa4): undefined reference to `pthread_setspecific'
    /usr/lib/erlang/lib/erl_interface-3.5.7/lib/libei.a(ei_pthreads.o): In
    function `__erl_errno_place':
    (.text+0xb6): undefined reference to `pthread_getspecific'
    /usr/lib/erlang/lib/erl_interface-3.5.7/lib/libei.a(ei_pthreads.o): In
    function `erl_errno_key_alloc':
    (.text+0x136): undefined reference to `pthread_key_create'
    /usr/lib/erlang/lib/erl_interface-3.5.7/lib/libei.a(ei_pthreads.o): In
    function `ei_m_trylock':
    (.text+0x189): undefined reference to `pthread_mutex_trylock'
    collect2: ld returned 1 exit status

    However, even after successful compilation, it still didn't work due to
    a runtime linker error on "__erl_errno":

    irb(main):001:0> require 'erlix'
    LoadError: /usr/local/lib/ruby/site_ruby/1.8/i686-linux/erlix.so:
    undefined symbol: __erl_errno -
    /usr/local/lib/ruby/site_ruby/1.8/i686-linux/erlix.so
    from /usr/local/lib/ruby/site_ruby/1.8/i686-linux/erlix.so
    from (irb):1

    After poking around header files, I decided that the way to fix this
    was:

    $ make clean
    $ make CPPFLAGS=-D_REENTRANT

    And it happily builds and runs the sample now. I don't know how
    configure.rb should decide for itself whether -D_REENTRANT is needed or
    not.

    A few more suggestions:

    (1) For converting objects to strings, you should implement a "to_s"
    method, not "puts". Current behaviour is rather un-rubylike:

    irb(main):008:0> t=ErlixTuple.new([a1,f,b,a2,i])
    => #<ErlixTuple:0xb7d78d74>
    irb(main):009:0> t
    => #<ErlixTuple:0xb7d78d74>
    irb(main):010:0> t.puts ## unexpected
    {atom1,17.000000,#Bin,atom2,101}
    => nil
    irb(main):011:0> t.to_s
    => "#<ErlixTuple:0xb7d78d74>" ## unexpected

    This would also allow you to interpolate terms into strings, e.g.

    puts "The response was #{t}"

    (2) It would be helpful if ErlixTurple took a variable number of
    arguments, instead of a single array. That would let you write

    ErlixTuple.new(a1,f,b,a2,i)

    This wouldn't prevent you from using an array if you like, because Ruby
    provides a 'splat' operator:

    arr = [a1,f,b,a2,i]
    ErlixTuple.new(*arr)

    Anyway, keep up the good work - this is looking promising!

    Regards,

    Brian.
     
    Brian Candler, Apr 29, 2009
    #8
  9. KDr2

    KDr2 Guest

    [Note: parts of this message were removed to make it a legal post.]

    Thank you, I just hava done little update :
    http://github.com/KDr2/erlix/tree/master#fn1

    I will go on and on ...

     
    KDr2, Apr 30, 2009
    #9
  10. Interesting.

    However I think it would be better to turn a ruby string into an erlang
    list, rather than an atom, for two reasons:

    (1) It more closely matches what happens in Erlang

    1> Foo = "abc".
    "abc"
    2> hd(Foo).
    97

    (2) I'm not an Erlang expert, but I think I read that Erlang has the
    same atom-exhaustion problem that Ruby has with symbols: namely that
    once an atom has been allocated it cannot be freed. So it is not a good
    idea to keep calling list_to_atom on random strings provided by
    untrusted users.

    I'd still expect Ruby symbols to be mapped to atoms, of course.

    Regards,

    Brian.
     
    Brian Candler, Apr 30, 2009
    #10
  11. KDr2

    KDr2 Guest

    You're right, String should be converted to List, thanks again=EF=BC=81


    --=20
    Best Regards,
    -- KDr2, at x-macro.com.
     
    KDr2, Apr 30, 2009
    #11
  12. KDr2

    KDr2 Guest

    I made some update today, and Erlix supports Ruby1.9.x now.

    There're also some other changes:
    1. All classes (Term/Int/List/Tuple/Atom/...) are under the Erlix module now
    2. new init method for Tuple/List:
    Erlix::List.new
    Erlix::List.new(1,2,3)
    Erlix::List.new([1,2,3])

    You can install it with gem or from the source, see docs at https://github.com/KDr2/erlix .

    This is an alpha version(0.5.0a). If you are interesting in this, please install and do some test, find bugs and send to me, Many Thanks.
     
    KDr2, Jul 25, 2012
    #12
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.