The make-custom-port
procedure described in the previous section
has similar functionality on the C level, though it is organized a bit
differently.
In C, the mechanism is that one creates a new port type object. The methods are then associated with the port type object instead of the port itself. The port type object is an opaque pointer allocated when defining the port type, which serves as a key into the port API.
Ports themselves have associated stream values. The stream is a
pointer controlled by the user, which is set when the port is created.
Given a port, the SCM_STREAM
macro returns its associated stream
value, as a scm_t_bits
. Note that your port methods are only
ever called with ports of your type, so port methods can safely cast
this value to the expected type. Contrast this to Scheme, which doesn’t
need access to the stream because the make-custom-port
methods
can be closures that share port-specific data directly.
A port type is created by calling scm_make_port_type
.
scm_t_port_type*
scm_make_port_type (char *name, size_t (*read) (SCM port, SCM dst, size_t start, size_t count), size_t (*write) (SCM port, SCM src, size_t start, size_t count))
¶Define a new port type. The name parameter is like the
#:id
parameter to make-custom-port
; and read and
write are like make-custom-port
’s #:read
and
#:write
, except that they should return (size_t)-1
if the
read or write operation would block, instead of #f
.
void
scm_set_port_read_wait_fd (scm_t_port_type *type, int (*wait_fd) (SCM port))
¶void
scm_set_port_write_wait_fd (scm_t_port_type *type, int (*wait_fd) (SCM port))
¶void
scm_set_port_print (scm_t_port_type *type, int (*print) (SCM port, SCM dest_port, scm_print_state *pstate))
¶void
scm_set_port_close (scm_t_port_type *type, void (*close) (SCM port))
¶void
scm_set_port_needs_close_on_gc (scm_t_port_type *type, int needs_close_p)
¶void
scm_set_port_seek (scm_t_port_type *type, scm_t_off (*seek) (SCM port, scm_t_off offset, int whence))
¶void
scm_set_port_truncate (scm_t_port_type *type, void (*truncate) (SCM port, scm_t_off length))
¶void
scm_set_port_random_access_p (scm_t_port_type *type, int (*random_access_p) (SCM port));
¶void
scm_set_port_input_waiting (scm_t_port_type *type, int (*input_waiting) (SCM port));
¶void
scm_set_port_get_natural_buffer_sizes (scm_t_port_type *type, void (*get_natural_buffer_sizes) (SCM, size_t *read_buf_size, size_t *write_buf_size))
¶Port method definitions. See Low-Level Custom Ports, for more details on each of these methods.
Once you have your port type, you can create ports with
scm_c_make_port
, or scm_c_make_port_with_encoding
.
SCM
scm_c_make_port_with_encoding (scm_t_port_type *type, unsigned long mode_bits, SCM encoding, SCM conversion_strategy, scm_t_bits stream)
¶SCM
scm_c_make_port (scm_t_port_type *type, unsigned long mode_bits, scm_t_bits stream)
¶Make a port with the given type. The stream indicates the
private data associated with the port, which your port implementation
may later retrieve with SCM_STREAM
. The mode bits should include
one or more of the flags SCM_RDNG
or SCM_WRTNG
, indicating
that the port is an input and/or an output port, respectively. The mode
bits may also include SCM_BUF0
or SCM_BUFLINE
, indicating
that the port should be unbuffered or line-buffered, respectively. The
default is that the port will be block-buffered. See Buffering.
As you would imagine, encoding and conversion_strategy
specify the port’s initial textual encoding and conversion strategy.
Both are symbols. scm_c_make_port
is the same as
scm_c_make_port_with_encoding
, except it uses the default port
encoding and conversion strategy.
At this point you may be wondering whether to implement your custom port
type in C or Scheme. The answer is that probably you want to use
Scheme’s make-custom-port
. The speed is similar between C and
Scheme, and ports implemented in C have the disadvantage of not being
suspendable. See Non-Blocking I/O.