Ada Binding

Source Code

http://github.com/persan/zeromq-Ada

Development environment

Linux

A modern gcc/gnat such as http://libre.adacore.com installed.
Or GCC 4.5 or better with Ada.

Windows

A modern gcc such as http://libre.adacore.com installed.
A set of posix build tools such as cygwin, with cygwin do not install gcc or have GNAT before it in the PATH.

Build and installation

You will first need to install the latest ØMQ from the development trunk here:
http://github.com/sustrik/zeromq2
Then download the zeromq-Ada source and cd to its top-level directory:

$ cd zeromq-Ada

Compile the stuff

$make

Finally install the package by running:

$ make install

You may have to run this last command with sudo.

Windows

Exact the same but you need ether cygwin or mingw as build environment

Sample code

A simple client/server application

This example implements a simple "SQL server" following the client/server model. The server listens to requests using unicast TCP. Each request is a simple string. Upon receiving a request the server will send back a canned response of OK, also as a string. All the samples are part of the package.

The server application, using Ada bindings:

with ZMQ.Sockets;
with ZMQ.Contexts;
with ZMQ.Messages;
with Ada.Text_IO; use Ada.Text_IO;

procedure ZMQ.examples.Server is
   ctx   : ZMQ.Contexts.Context;
   s     : ZMQ.Sockets.Socket;
   resultset_string : constant String := "OK";
begin
   --  Initialise 0MQ context, requesting a single application thread
   --  and a single I/O thread
   ctx.Initialize (1);

   --   Create a ZMQ_REP socket to receive requests and send replies
   s.Initialize (ctx, Sockets.REP);

   --   Bind to the TCP transport and port 5555 on the 'lo' interface
   s.Bind ("tcp://lo:5555");

   loop
      declare
         query : ZMQ.Messages.Message;
      begin
         query.Initialize;
         --  Receive a message, blocks until one is available
         s.recv (query, 0);
         --  Process the query
         Put_Line (query.getData);
         declare
            --  Allocate a response message and fill in an example response
            resultset : ZMQ.Messages.Message;
         begin
            resultset.Initialize (query.getData & "->" & resultset_string);
            --   Send back our canned response
            s.Send (resultset);
            resultset.Finalize;
         end;
         query.Finalize;
      end;

   end loop;
end ZMQ.Examples.Server;

The client application, using Ada bindings:

with ZMQ.Sockets;
with ZMQ.Contexts;
with ZMQ.Messages;
with Ada.Text_IO; use Ada.Text_IO;

procedure ZMQ.examples.Client is
   ctx              : ZMQ.Contexts.Context;
   s                : ZMQ.Sockets.Socket;
begin
   --  Initialise 0MQ context, requesting a single application thread
   --  and a single I/O thread
   ctx.Initialize (1);

   --   Create a ZMQ_REP socket to receive requests and send replies
   s.Initialize (ctx, Sockets.REQ);

   --   Bind to the TCP transport and port 5555 on the 'lo' interface
   s.Connect ("tcp://localhost:5555");
   for i in  1 .. 10 loop
      declare
         query_string : constant String := "SELECT * FROM mytable";
         query        : ZMQ.Messages.Message;
      begin
         query.Initialize (query_string & "(" & i'Img & ");");
         s.Send (query);
         query.Finalize;
      end;

      declare
         resultset        : ZMQ.Messages.Message;
      begin
         resultset.Initialize;
         s.recv (resultset);
         Put_Line ('"' & resultset.getData & '"');
         resultset.Finalize;
      end;
   end loop;
end ZMQ.Examples.Client;

Finally the multi-threaded server

with ZMQ.Sockets;
with ZMQ.Contexts;
with ZMQ.devices;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
procedure ZMQ.examples.Multi_Thread_Server is

   task type server_task (ctx : not null access ZMQ.Contexts.Context;
                          id  : Integer) is
   end server_task;

   task body server_task is
      msg : Ada.Strings.Unbounded.Unbounded_String;
      s   : ZMQ.Sockets.Socket;
   begin
      s.Initialize (ctx.all, Sockets.REP);
      s.Connect ("inproc://workers");
      loop
         msg := s.recv;
         Append (msg, "<Served by thread:" & id'Img & ">");
         s.Send (msg);
      end loop;
   end server_task;

   ctx              : aliased ZMQ.Contexts.Context;

   Number_Of_Servers : constant := 10;
   servers          : array (1 .. Number_Of_Servers) of access server_task;

   workers          : ZMQ.Sockets.Socket;
   clients          : ZMQ.Sockets.Socket;

   dev              : ZMQ.devices.device;

begin
   --  Initialise 0MQ context, requesting a single application thread
   --  and a single I/O thread
   ctx.Initialize (servers'Length + 1);

   --   Create a ZMQ_REP socket to receive requests and send replies
   workers.Initialize (ctx, Sockets.XREQ);
   workers.Bind ("inproc://workers");

   --   Bind to the TCP transport and port 5555 on the 'lo' interface
   clients.Initialize (ctx, Sockets.XREP);
   clients.Bind ("tcp://lo:5555");

   for i in servers'Range loop
      servers (i) := new server_task (ctx'Access, i);
   end loop;

   dev.initialize (devices.Queue, clients, workers);

end ZMQ.Examples.Multi_Thread_Server;

To build this example, ensure that you have the ØMQ adabindings installed and run the following:
gprbuild -p -P zmq-examples

You can then run bin/server and bin/client.

Documentation

The README file of the source code is the best documentation for now.

Test Suite

zeromq-Ada has an integrated test suite, to be completed!

$ make test

Bug Reporting

If you encounter problems please fill a bug report at:

http://github.com/persan/zeromq-Ada/issues

Discussions about this language binding take place on the general zeromq-dev list.