github
Advanced Search
  • Home
  • Pricing and Signup
  • Explore GitHub
  • Blog
  • Login

KDr2 / erlix

  • Admin
  • Watch Unwatch
  • Fork
  • Your Fork
  • Pull Request
  • Download Source
    • 55
    • 2
  • Source
  • Commits
  • Network (2)
  • Issues (0)
  • Downloads (0)
  • Wiki (1)
  • Graphs
  • Branch: master

click here to add a description

click here to add a homepage

  • Branches (1)
    • master ✓
  • Tags (0)
Sending Request…
Enable Donations

Pledgie Donations

Once activated, we'll place the following badge in your repository's detail box:
Pledgie_example
This service is courtesy of Pledgie.

Ruby Interface of Erlang — Read more

  cancel

http://github.com/KDr2/erlix/

  cancel
  • Private
  • Read-Only
  • HTTP Read-Only

This URL has Read+Write access

readme update 
KDr2 (author)
Wed Jan 06 18:44:36 -0800 2010
commit  d45337c18f90c3d29abf5982e3d415fe60a6f477
tree    a061706d8af2c2b92a171fb9ee564470f6cda4c2
parent  7f1a5371e8ab36838f809fcc72828601e804a0ac
erlix /
name age
history
message
file README.textile Wed Jan 06 18:44:36 -0800 2010 readme update [KDr2]
file configure.rb Thu Apr 30 18:34:31 -0700 2009 add ErlixTerm.to_s,remove ErlixTerm.puts,fix so... [KDr2]
directory docs/ Wed Apr 29 00:37:53 -0700 2009 README update [KDr2]
file extconf.rb Tue Apr 28 05:29:09 -0700 2009 v0.2 [KDr2]
file findei.erl Tue Apr 28 05:29:09 -0700 2009 v0.2 [KDr2]
directory src/ Tue Jul 21 02:18:03 -0700 2009 add method ErlixTerm#inspect [KDr2]
directory test/ Sun May 10 08:15:22 -0700 2009 Revert "fix test code bug,issue 1" This revert... [KDr2]
README.textile

Erlix Tutorial

Changelog

20090430 update

  • features:
    • Type auto-convert1
    • [] singleton method for ErlixTuple and ErlixList2
    • add ErlixTerm.to_s, remove ErlixTerm.puts

erlix-v0.3 changelog:

  • bugfix:
    • IO block bug in ErlixConnection#erecv
  • feature:
    • ErlixList#new(“string”)
    • ErlixConnection#close
    • ErlixConnection#closed?
    • ErlixConnection#rpc(“module”,“function”,ErlixTermList)
    • ErlixConnection#peer

Intsall erlix

On Linux/Unix only,need erlang installed.


unzip erlix-version.zip
cd erlix-version
ruby configure.rb
make
make install

Play with the ErlixTerm

ErlixTerm is a Module, represents the erlang-term, It is mixed into some particular classes,like ErlixAtom,ErlixInt,ErlixList… Now we will play with these classes in irb,

First,open irb,and require the erlix lib:


kdr2@kdr2-pc:~$ irb
irb(main):001:0> require "erlix"
=> true
irb(main):002:0>

Find all ErlixTerm’s subclasses:


irb(main):002: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):003:0>

We see,there are 9 ErlixTerm classes we hava implemented:

  1. ErlixBinary
  2. ErlixTuple
  3. ErlixList
  4. ErlixAtom
  5. ErlixRef
  6. ErlixPid
  7. ErlixFloat
  8. ErlixUInt
  9. ErlixInt

Here we go on:


irb(main):003:0> a1=ErlixAtom.new("atom1")
=> #<ErlixAtom:atom1>
irb(main):004:0> a2=ErlixAtom.new("atom2")
=> #<ErlixAtom:atom2>
irb(main):005:0> f=ErlixFloat.new(17.0)
=> #<ErlixFloat:17.000000>
irb(main):006:0> b=ErlixBinary.new("data\0data")
=> #<ErlixBinary:#Bin>
irb(main):007:0> b.data
=> "data\000data"
irb(main):008:0> i=ErlixInt.new(101)
=> #<ErlixInt:101>
irb(main):009:0> t=ErlixTuple.new([a1,f,b,a2,i])
=> #<ErlixTuple:{atom1,17.000000,#Bin,atom2,101}>
irb(main):010:0> list=ErlixList.new([a1,i,t])
=> #<ErlixList:[atom1,101,{atom1,17.000000,#Bin,atom2,101}]>
irb(main):011:0> t[2]
=> #<ErlixFloat:17.000000>
irb(main):012:0> t[2].class
=> ErlixFloat
irb(main):013:0> t[3].class
=> ErlixBinary
irb(main):014:0> t.nth(3)==t[3]
=> true
irb(main):015:0> list.head
=> #<ErlixAtom:atom1>
irb(main):016:0> list.tail
=> #<ErlixList:[101,{atom1,17.000000,#Bin,atom2,101}]>
irb(main):017:0> list2=list.cons(b)
=> #<ErlixList:[#Bin,atom1,101,{atom1,17.000000,#Bin,atom2,101}]>

Some Ruby-Type var can be auto-converted to particular Erlang-Type:

Ruby-Type → Erlang-Type
FixNum → ErlixInt
Float → ErlixFloat
String → ErlixList
Symbol → ErlixAtom

See below


irb(main):016:0> c=ErlixList.new(["string-to-list",1,:symbol_to_atom,1.00])
=> #<ErlixList:["string-to-list",1,symbol_to_atom,1.000000]>
irb(main):017:0> c.head.class
=> ErlixList
irb(main):019:0>

Use singleton method [] to create ErlixTuple/ErlixList


irb(main):019:0> c=ErlixList["string-to-list",1,:symbol_to_atom,1.00]
=> #<ErlixList:["string-to-list",1,symbol_to_atom,1.000000]>
irb(main):020:0> t=ErlixTuple["string-to-list",1,:symbol_to_atom,1.00]
=> #<ErlixTuple:{"string-to-list",1,symbol_to_atom,1.000000}>
irb(main):021:0> t[1]
=> #<ErlixList:"string-to-list">
irb(main):022:0> t[3]
=> #<ErlixAtom:symbol_to_atom>
irb(main):023:0> sl=%w[abc def xyz]
=> #<ErlixList:["abc", "def", "xyz"]>
irb(main):024:0> ErlixTuple[*sl]
=> #<ErlixTuple:{"abc","def","xyz"}>

And we can use match to test a ErlixTerm’s format, use mget to get a particular ErlixTerm inside a ErlixTerm:


irb(main):023:0> list2
=> #<ErlixList:[#Bin,atom1,101,{atom1,17.000000,#Bin,atom2,101}]>
irb(main):024:0> list2.match("[B,Atom,101,Tuple]")
=> true
irb(main):025:0> list2.match("[nomatch,B,Atom,101,Tuple]")
=> false
irb(main):027:0> t2=list2.mget("[B,Atom,101,Tuple]","Tuple")
=> #<ErlixTuple:{atom1,17.000000,#Bin,atom2,101}>

Play with the Real-Erlang-Node

First write a erlang module for our test:


-module(test).
-compile(export_all).
loop()->
    %% receive msg,the msg's format is {FromPid,Msg}
    %% the FromPid is a pid in our ruby program,
    %% we use "FromPid ! Msg" to echo the Msg back
    receive
        {FromPid,Msg} ->
            io:format("From:[~w], MSG From Ruby:[~w] ~n",[FromPid,Msg]),
            FromPid ! Msg,
            loop()
    end.

run()->
    Pid=spawn(fun loop/0),
    %% Associates the name "my_pid" with Pid
    %% so that our ruby code can find this pid and send message to it!
    register(my_pid,Pid).

Then we satrt an Erlang-Node to run the test module,you must give the erlang-node a short name or name:


kdr2@kdr2-pc:~/work/erlix/test$ erl -sname foo
Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]

Eshell V5.6.5  (abort with ^G)
(foo@kdr2-pc)1> c(test).
{ok,test}
(foo@kdr2-pc)2> test:run().
true
(foo@kdr2-pc)3>

My hostname is “kdr2-pc”, with the option “-sname foo”,the erlang-node name is “foo@kdr2-pc”.

The time we write ruby code with erlix now:


#!/usr/bin/ruby
# -*- coding: utf-8 -*-

require "erlix"

# init ErlixNode,
#  the first argument is the short-name of the ErlixNode
#  the second argument is the erlang cookie, use nil it's will read ~/.erlang.cookie
# after init, my ErlixNode's name is inited to "ruby@kdr2-pc"
ErlixNode.init("ruby",nil)

# connect to the real Erlang-Node:
c=ErlixConnection.new("foo@kdr2-pc")
puts "connect ok"

# create a new Pid with the connection
# we will use this Pid as the FromPid
p=ErlixPid.new(c)

# make a ErlixTuple {Pid,test_atom} and send it to the real erlang-node
c.esend("my_pid",ErlixTuple.new([p,ErlixAtom.new("test_atom")]))
puts "send ok"

# start a new thread to receive the msg from the real erlang-node
puts "receiving"
t=Thread.new{
  while true do
    #in erlix-v0.2,erecv make all threads blocked,v0.3 fixed this
    m=c.erecv
    puts m.mtype
    puts m.message
    puts m.class
    puts m.from
    puts m.to
  end
}

t.join

Run the test code:


kdr2@kdr2-pc:~/work/erlix$ ruby test/erlix_test.rb
connect ok
send ok
receiving
ERL_SEND
test_atom
ErlixMessage
nil
<3.6.3>
...

The output of erlang:


(foo@kdr2-pc)2> test:run().
true
From:[<6027.3.6>], MSG From Ruby:[test_atom]
(foo@kdr2-pc)3>

Note : the class ErlixMessage:
The method ErlixConnection#erecv return an instance of ErlixMessage, ErlixMessage represents the struct ErlMessge in erl_interface,it has several fields:

  1. type
  2. msg
  3. from
  4. to
    You can call ErlixMessage#mtype,ErlixMessage#message,ErlixMessage#from,ErlixMessage#to to get them.
    There’s the description of ErlMessage from the erl_connect manual:

     This function receives the message into the specified buffer, and decodes into the (ErlMessage *) emsg.

              fd is an open descriptor to an Erlang connection.

              bufp is a buffer large enough to hold the expected message.

              bufsize indicates the size of bufp.

              emsg is a pointer to an ErlMessage structure, into which the message will be decoded. ErlMessage is defined as follows:

              typedef struct {
                int type;
                ETERM *msg;
                ETERM *to;
                ETERM *from;
                char to_name[MAXREGLEN];
              } ErlMessage;

   Note:
       The definition of ErlMessage has changed since earlier versions of Erl_Interface.

       type identifies the type of message, one of ERL_SEND, ERL_REG_SEND, ERL_LINK, ERL_UNLINK and ERL_EXIT.

       If  type  contains  ERL_SEND  this indicates that an ordinary send operation has taken place, and emsg->to contains the Pid of the
       recipient. If type contains ERL_REG_SEND then a registered send operation took place, and  emsg->from  contains  the  Pid  of  the
       sender. In both cases, the actual message will be in emsg->msg.

       If  type contains one of ERL_LINK or ERL_UNLINK, then emsg->to and emsg->from contain the pids of the sender and receipient of the
       link or unlink. emsg->msg is not used in these cases.

       If type contains ERL_EXIT, then this indicates that a link has been broken. In this case, emsg->to and emsg->from contain the pids
       of the linked processes, and emsg->msg contains the reason for the exit.

Erlix RPC


c=ErlixConnection.new("foo@kdr2-pc")

#rpc call
fmt=ErlixList.new("abc~n")
tmp=ErlixList.new(nil)
args=ErlixList.new([fmt,tmp])
ret=c.rpc("io","format",args)
puts ret;
puts ret.class

Note : Before you make a ErlixConnection#rpc call, ErlixConnection#erecv and ErlixConnection#esend calls must be stopped(There may be an thread runing and blocking on erecv call,you can make rpc-thead and erecv-thread as two mutual exclusive threads). After the ErlixConnection#rpc returned ErlixConnection#erecv and ErlixConnection#esend can be called again.

EOF

Blog | Support | Training | Contact | API | Status | Twitter | Help | Security
© 2010 GitHub Inc. All rights reserved. | Terms of Service | Privacy Policy
Powered by the Dedicated Servers and
Cloud Computing of Rackspace Hosting®
Dedicated Server