## 3 Using the Erlang Generic Server Back-end

### 3.1 Introduction

The mapping of OMG IDL to the Erlang programming language when Erlang generic server is the back-end of choice is similar to the one used in the chapter 'OMG IDL Mapping'. The only difference is on the generated code, a client stub and server skeleton to an Erlang `gen_server`.

### 3.2 Compiling the Code

In the Erlang shell type :

`ic:gen(<filename>, [{be, erl_genserv}])`.

### 3.3 Writing the Implementation File

For each IDL interface `<interface name>` defined in the IDL file :

- Create the coresponding Erlang file that will hold the Erlang implementation of the IDL definitions.
- Call the implementation file after the scope of the IDL interface, followed by the suffix `_impl`.
- Export the implementation functions.

For each function defined in the IDL interface :

- Implement an Erlang function that uses as arguments in the same order, as the input arguments described in the IDL file, and returns the value described in the interface.
- When using the function, follow the mapping described in chapter 2.

### 3.4 An Example

In this example, a file "random.idl" generates code for the plain erlang back-end :

- Main file : "random.idl"

      module rmod {

        interface random {

          double produce();

          oneway void init(in long seed1, in long seed2, in long seed3);

        };

      };

Compile the file :

          Erlang BEAM) emulator version 4.9

          Eshell V4.9  (abort with ^G)
          1> ic:gen(random,[{be, erl_genserv}]).
          Erlang IDL compiler version 2.5.1
          ok
          2>

When the file "random.idl" is compiled it produces five files: two for the top scope, two for the interface scope, and one for the module scope. The header files for top scope and interface are empty and not shown here. In this case, only the file for the interface `rmod_random.erl` is important :.

- Erlang file for interface : "rmod_random.erl"

      -module(rmod_random).

      %% Interface functions
      -export([produce/1, init/4]).

      %% Type identification function
      -export([typeID/0]).

      %% Used to start server
      -export([oe_create/0, oe_create_link/0, oe_create/1]).
      -export([oe_create_link/1, oe_create/2, oe_create_link/2]).

      -export([start/2, start_link/3]).

      %% gen server export stuff
      -behaviour(gen_server).
      -export([init/1, terminate/2, handle_call/3]).
      -export([handle_cast/2, handle_info/2]).

      %%------------------------------------------------------------
      %%
      %% Object interface functions.
      %%
      %%------------------------------------------------------------

      %%%% Operation: produce
      %%
      %%   Returns: RetVal
      %%
      produce(OE_THIS) ->
          gen_server:call(OE_THIS, produce, infinity).

      %%%% Operation: init
      %%
      %%   Returns: RetVal
      %%
      init(OE_THIS, Seed1, Seed2, Seed3) ->
          gen_server:cast(OE_THIS, {init, Seed1, Seed2, Seed3}).

      %%------------------------------------------------------------
      %%
      %% Server implementation.
      %%
      %%------------------------------------------------------------

      %%------------------------------------------------------------
      %%
      %% Function for fetching the interface type ID.
      %%
      %%------------------------------------------------------------

      typeID() ->
          "IDL:rmod/random:1.0".

      %%------------------------------------------------------------
      %%
      %% Server creation functions.
      %%
      %%------------------------------------------------------------

      oe_create() ->
          start([], []).

      oe_create_link() ->
          start_link([], []).

      oe_create(Env) ->
          start(Env, []).

      oe_create_link(Env) ->
          start_link(Env, []).

      oe_create(Env, RegName) ->
          start(RegName, Env, []).

      oe_create_link(Env, RegName) ->
          start_link(RegName, Env, []).

      %%------------------------------------------------------------
      %%
      %% Start functions.
      %%
      %%------------------------------------------------------------

      start(Env, Opt) ->
          gen_server:start(?MODULE, Env, Opt).

      start_link(Env, Opt) ->
          gen_server:start_link(?MODULE, Env, Opt).

      start(RegName, Env, Opt) ->
          gen_server:start(RegName, ?MODULE, Env, Opt).

      start_link(RegName, Env, Opt) ->
          gen_server:start_link(RegName, ?MODULE, Env, Opt).

      init(Env) ->
      %% Call to implementation init
          rmod_random_impl:init(Env).

      terminate(Reason, State) ->
          rmod_random_impl:terminate(Reason, State).

      %%%% Operation: produce
      %%
      %%   Returns: RetVal
      %%
      handle_call(produce, OE_From, OE_State) ->
          rmod_random_impl:produce(OE_State);

      %%%% Standard Operation: oe_get_interface
      %%
      handle_call({OE_THIS, oe_get_interface, []}, From, State) ->
          {reply, [{"produce",{tk_double,[],[]}},
                   {"init",{tk_void,[tk_long,tk_long,tk_long],[]}}], State};

      %%%% Standard gen_server call handle
      %%
      handle_call(stop, From, State) ->
          {stop, normal, ok, State}.

      %%%% Operation: init
      %%
      %%   Returns: RetVal
      %%
      handle_cast({init, Seed1, Seed2, Seed3}, OE_State) ->
          rmod_random_impl:init(OE_State, Seed1, Seed2, Seed3);

      %%%% Standard gen_server cast handle
      %%
      handle_cast(stop, State) ->
          {stop, normal, State}.

      %%%% Standard gen_server handles
      %%
      handle_info(X, State) ->
          {noreply, State}.

The implementation file should be called `rmod_random_impl.erl` and could look like this :

    -module('rmod_random_impl').
    -export([init/1, terminate/2]).
    -export([produce/1,init/4]).

    init(Env) ->
        {ok, []}.

    terminate(From, Reason) ->
        ok.

    produce(_Random)  ->
        case catch random:uniform() of
            {'EXIT',_} ->
                true;
            RUnif ->
                {reply,RUnif,[]}
         end.

    init(_Random,S1,S2,S3)  ->
        case catch random:seed(S1,S2,S3) of
            {'EXIT',_} ->
                true;
            _ ->
                {noreply,[]}
        end.

Compiling the code :

    2> make:all().
    Recompile: rmod_random
    Recompile: oe_random
    Recompile: rmod_random_impl
    up_to_date

Running the example :

    3> {ok,R} =  rmod_random:oe_create().
    {ok,<0.30.0>
    4> rmod_random:init(R,1,2,3).
    ok
    5> rmod_random:produce(R).
    1.97963e-4
    6>

Copyright © 1991-2002 Ericsson Utvecklings AB