Ruby Interface of Erlang

Hello, erveyone,I just start a new project called erlix,the ruby
interface
for erlang,at Google Code Archive - Long-term storage for Google Code Project Hosting. ,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.

On Monday 27 April 2009 10:49:48 KDr2 wrote:

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

How does this compare to Erlectricity?

http://code.google.com/p/erlectricity

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

:slight_smile:

KDr2 wrote:

see the section Erlix RPC on
Google Code Archive - Long-term storage for Google Code Project Hosting.

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.

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”)

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

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

ErlixConnection?http://code.google.com/p/erlix/w/edit/ErlixConnection
#rpc(“module”,“function”,ErlixTermList?http://code.google.com/p/erlix/w/edit/ErlixTermList)

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

Thank you for your advise :slight_smile: They are very useful for me.

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[i];
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 C. wrote:

BTW, I haven’t been able to get it to build yet - it’s stuck looking for
-lei

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 topthread_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 topthread_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 topthread_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 topthread_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 topthread_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 topthread_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.

KDr2 wrote:

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

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.

You’re right, String should be converted to List, thanks again!

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

I will go on and on …