perl erlang プロセス間で直接メッセージを送受信する

単純に erl_interface を Inline::C から使っただけなんですが(w;

erlang 側の準備

特別な準備は無し。
とりあえず、送受信するプロセスを適当に作っておく。

-module(pingpong).
-compile(export_all).

start() -> register(pingpong, spawn(?MODULE, loop, [])).
stop()  -> pingpong ! stop.

loop() ->
  receive
    stop ->
      io:fwrite("~w:stop.~n", [self()]),
      exit(ok);
    {message, Pid, Message} ->
      io:fwrite("Pid:~w~nMessage:~s~n", [Pid, Message]),
      Pid ! {message, self(), "pong"};
    Other ->
      io:fwrite("Other:~w~n", [Other])
  end,
  loop().
% erlc pingpong.erl
% erl -name test@`hostname` -s pingpong start

perl 側の準備

http://labs.miu.vc/svn/cooldaemon/perl/Erlang-Interface/lib を任意の場所に設置。
lib/Erlang/Interface/InlineC.pm の下記の LIBS と INC を適切なパスに書き換える。

use Inline C => Config    ## no critic
  => CCFLAGS => '-std=c99'
  => LIBS => '-L/opt/local/lib/erlang/lib/erl_interface-3.5.5.3/lib -lerl_interface -lei'
  => INC  => '-I/opt/local/lib/erlang/lib/erl_interface-3.5.5.3/include';

erlang プロセスとメッセージを送受信するスクリプトを書く。

#!/usr/bin/env perl

use strict;
use warnings;
use feature qw(:5.10);

use version; our $VERSION = qv('0.0.1');

use Carp;
use English qw(-no_match_vars);

use Erlang::Interface;

my $eif = Erlang::Interface->new;
say $eif->node();
my $fd = $eif->connect(alive => 'test');

my $atom = Erlang::Interface::Eterm->make_atom('message');
my $string = Erlang::Interface::Eterm->make_string('ping');
my $pid = $fd->self_pid;

my $tuple = Erlang::Interface::Eterm->make_tuple($atom, $pid, $string,);
$fd->reg_send('pingpong', $tuple) or croak 'send error.';

my $recv = $fd->receive() or croak 'receive error.';
if ($recv->is_tuple) {
    for ($recv->value) {
        if ($_->is_pid) {
            $fd->send($_, $tuple) or croak 'send error';
            next;
        }
        say $_->value;
    }
}

試す

% perl pingpong.pl
A9D28758-DAC7-11DC-89C1-DF2240E9B49D@xxxxxx.jp
message
pong

今後

rpc を実装する。
対応した

my $string = Erlang::Interface::Eterm->make_string('hello!!');
my $args   = Erlang::Interface::Eterm->make_list($string);

my $recv0 = $fd->rpc('io', 'fwrite', $args) or croak 'rpc error.';
say $recv->value;

$fd->rpc_send('io', 'fwrite', $args) or croak 'rpc_send error.';
my $recv1 = $fd->rpc_receive() or croak 'rpc_receive error.';
say $recv1->value;

Global Names に対応する。