Next: , Up: I/O Extensions


5.12.10.1 C Port Interface

This section describes how to use Scheme ports from C.

Port basics

There are two main data structures. A port type object (ptob) is of type scm_ptob_descriptor. A port instance is of type scm_port. Given an SCM variable which points to a port, the corresponding C port object can be obtained using the SCM_PTAB_ENTRY macro. The ptob can be obtained by using SCM_PTOBNUM to give an index into the scm_ptobs global array.

Port buffers

An input port always has a read buffer and an output port always has a write buffer. However the size of these buffers is not guaranteed to be more than one byte (e.g., the shortbuf field in scm_port which is used when no other buffer is allocated). The way in which the buffers are allocated depends on the implementation of the ptob. For example in the case of an fport, buffers may be allocated with malloc when the port is created, but in the case of an strport the underlying string is used as the buffer.

The rw_random flag

Special treatment is required for ports which can be seeked at random. Before various operations, such as seeking the port or changing from input to output on a bidirectional port or vice versa, the port implementation must be given a chance to update its state. The write buffer is updated by calling the flush ptob procedure and the input buffer is updated by calling the end_input ptob procedure. In the case of an fport, flush causes buffered output to be written to the file descriptor, while end_input causes the descriptor position to be adjusted to account for buffered input which was never read.

The special treatment must be performed if the rw_random flag in the port is non-zero.

The rw_active variable

The rw_active variable in the port is only used if rw_random is set. It's defined as an enum with the following values:

SCM_PORT_READ
the read buffer may have unread data.
SCM_PORT_WRITE
the write buffer may have unwritten data.
SCM_PORT_NEITHER
neither the write nor the read buffer has data.
Reading from a port.

To read from a port, it's possible to either call existing libguile procedures such as scm_getc and scm_read_line or to read data from the read buffer directly. Reading from the buffer involves the following steps:

  1. Flush output on the port, if rw_active is SCM_PORT_WRITE.
  2. Fill the read buffer, if it's empty, using scm_fill_input.
  3. Read the data from the buffer and update the read position in the buffer. Steps 2) and 3) may be repeated as many times as required.
  4. Set rw_active to SCM_PORT_READ if rw_random is set.
  5. update the port's line and column counts.
Writing to a port.

To write data to a port, calling scm_lfwrite should be sufficient for most purposes. This takes care of the following steps:

  1. End input on the port, if rw_active is SCM_PORT_READ.
  2. Pass the data to the ptob implementation using the write ptob procedure. The advantage of using the ptob write instead of manipulating the write buffer directly is that it allows the data to be written in one operation even if the port is using the single-byte shortbuf.
  3. Set rw_active to SCM_PORT_WRITE if rw_random is set.