Communication via Queues

## 5.5 Communication via Queues

- From-ECLiPSe to Tcl
- To-ECLiPSe from Tcl

The most flexible way of passing data between ECLiPSe and Tcl is via the I/O facilities of the two languages, ie. via ECLiPSe queue streams which can be connected to Tcl channels.

Currently, a communication channel between ECLiPSe and Tcl is created from Tcl, which appears as an ECLiPSe queue in ECLiPSe, and a channel in Tcl. The queue has a symbolic name and a stream number in ECLiPSe, and has a channel name in Tcl. Facilities are provided to interconvert between these names.

Queues pass data between ECLiPSe and Tcl in one direction: either from ECLiPSe to Tcl (from-ECLiPSe), or from Tcl to ECLiPSe (to-ECLiPSe). Queues are created with the direction specified. The queues should be viewed as communication channels: data is written to the queue, and it only becomes available to the other side when the queue is flushed. This is done by calling the predicate flush/1 on the ECLiPSe side, and by invoking ec_flush on the Tcl side. The flush also has the effect of briefly transferring control to the other side to allow handlers to handle the data (see section 5.6)1

ec_queue_create eclipse_stream_name mode ?command? ?event?
  Creates a queue between Tcl and ECLiPSe. On the Tcl side, a Tcl channel is created. On the ECLiPSe side, the queue would be given the symbolic name eclipse_stream_name. The mode argument indicates the direction of the queue, and can either be fromec or toec2. The procedure returns a channel identifier for use in commands like puts, read, ec_read_exdr, ec_write_exdr or close. The optional arguments command and event specifies the data handler for the queue: command is the name of the Tcl procedure for handling the data, with its user defined arguments. event is the name of the event that will be raised on the ECLiPSe side. As a handler can only be defined for one side, either event or command should be undefined (`{}`).
ec_queue_close eclipse_stream_name
  Closes the queue with the ECLiPSe name of ec_stream_name.
ec_stream_nr eclipse_stream_name
  This command returns the ECLiPSe stream number given a symbolic stream name (this is the same operation that the ECLiPSe built-in get_stream/2 performs).
ec_streamname_to_streamnum eclipse_stream_name
  This is an alias for ec_stream_nr for compatibility purposes.
ec_streamname_to_channel eclipse_stream_name
  Returns the Tcl channel name for the queue with the symbolic name eclipse_name.
ec_streamnum_to_channel eclipse_stream_number
  Returns the Tcl channel name for the queue with the ECLiPSe stream number eclipse_stream_number.
ec_async_queue_create eclipse_stream_name mode ?command? ?event?
  This is provided mainly for compatibility with the Tcl remote interface. The command is an alias for ec_queue_create in the embedding interface. Certain uses of the queues in the embedding interface cannot be duplicated using the synchronous queues of the remote interface. Instead, asynchronous queues are needed (see chapter 6 for more details). This command is provided to allow the same code to be used for both interfaces. Note that it is possible to use the asynchronous queues of the remote interface in ways that are incompatible with the embedding interface.

### 5.5.1 From-ECLiPSe to Tcl

To create a queue from ECLiPSe to Tcl, use ec_queue_create with the mode argument set to fromec, e.g.

>     Tcl:            set my_in_channel [ec_queue_create my_out_queue fromec]

Once the queue is created, it can be used, e.g. by writing into it with ECLiPSe’s write/2 builtin, and reading using Tcl’s read command:

>     ECLiPSe:        write(my_out_queue, hello),
>                     flush(my_out_queue).

>     Tcl:            set result [read $my_in_channel 5]

The disadvantage of using these low-level primitives is that for reading one must know exactly how many bytes to read. It is therefore recommended to use the EXDR (ECLiPSe external data representation, see section 5.8) format for communication. This allows to send and receive structured and typed data. The primitives to do that are write_exdr/2 on the ECLiPSe side and ec_read_exdr (section 5.8) on the Tcl side:

>     ECLiPSe:        write_exdr(my_out_queue, foo(bar,3)),
>                     flush(my_out_queue).

>     Tcl:            set result [ec_read_exdr $my_in_channel]

In the example, the Tcl result will be the list {foo bar 3}. For details about the mapping see section 5.8.

### 5.5.2 To-ECLiPSe from Tcl

To create a queue from Tcl to ECLiPSe to Tcl, use ec_queue_create with the mode argument set to toec, e.g.

>     Tcl:            set my_out_channel [ec_queue_create my_in_queue toec]

Now the queue can be used, e.g. by writing into it with Tcl’s puts command and by reading using ECLiPSe’s read_string/4 builtin:

>     Tcl:            puts $my_out_channel hello
>                     ec_flush [ec_streamname_to_streamnum my_in_queue] 5

>     ECLiPSe:        read_string(my_in_queue, "", 5, Result).

The disadvantage of using these low-level primitives is that for reading one must know exactly how many bytes to read, or define a delimiter character. It is therefore recommended to use the EXDR (ECLiPSe external data representation, see section 5.8) format for communication. This allows to send and receive structured and typed data. The primitives to do that are ec_read_exdr (section 5.8) on the Tcl side and read_exdr/2 on the ECLiPSe side:

>     Tcl:            ec_write_exdr $my_out_channel {foo bar 3} (SI)
>                     ec_flush [ec_streamname_to_streamnum my_in_queue]

>     ECLiPSe:        read_exdr(my_in_queue, Result).

In the example, the ECLiPSe result will be the term foo("bar",3). For details about the mapping see section 5.8.

1
  Strictly speaking, flushing is not necessary in the embedding case to make the data available to the other side. However, it is needed in the remote case, and for compatibility and good practice, flushing is recommended.
2
  For compatibility with previous versions of the embedding Tcl interface, the mode can also be specified as r (equivalent to fromec) or w (equivalent to toec). These can be somewhat confusing as read/write status depends on from which side the queue is viewed (a read queue in ECLiPSe is a write queue in Tcl).