244 lines
16 KiB
HTML
244 lines
16 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<!-- Created by GNU Texinfo 7.1, https://www.gnu.org/software/texinfo/ -->
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<!-- This manual documents Guile version 3.0.10.
|
|
|
|
Copyright (C) 1996-1997, 2000-2005, 2009-2023 Free Software Foundation,
|
|
Inc.
|
|
|
|
Copyright (C) 2021 Maxime Devos
|
|
|
|
Copyright (C) 2024 Tomas Volf
|
|
|
|
|
|
Permission is granted to copy, distribute and/or modify this document
|
|
under the terms of the GNU Free Documentation License, Version 1.3 or
|
|
any later version published by the Free Software Foundation; with no
|
|
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
|
|
copy of the license is included in the section entitled "GNU Free
|
|
Documentation License." -->
|
|
<title>Low-Level Custom Ports (Guile Reference Manual)</title>
|
|
|
|
<meta name="description" content="Low-Level Custom Ports (Guile Reference Manual)">
|
|
<meta name="keywords" content="Low-Level Custom Ports (Guile Reference Manual)">
|
|
<meta name="resource-type" content="document">
|
|
<meta name="distribution" content="global">
|
|
<meta name="Generator" content=".texi2any-real">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
|
|
<link href="index.html" rel="start" title="Top">
|
|
<link href="Concept-Index.html" rel="index" title="Concept Index">
|
|
<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
|
|
<link href="Port-Types.html" rel="up" title="Port Types">
|
|
<link href="Low_002dLevel-Custom-Ports-in-C.html" rel="next" title="Low-Level Custom Ports in C">
|
|
<link href="Void-Ports.html" rel="prev" title="Void Ports">
|
|
<style type="text/css">
|
|
<!--
|
|
a.copiable-link {visibility: hidden; text-decoration: none; line-height: 0em}
|
|
div.example {margin-left: 3.2em}
|
|
span:hover a.copiable-link {visibility: visible}
|
|
strong.def-name {font-family: monospace; font-weight: bold; font-size: larger}
|
|
-->
|
|
</style>
|
|
<link rel="stylesheet" type="text/css" href="https://www.gnu.org/software/gnulib/manual.css">
|
|
|
|
|
|
</head>
|
|
|
|
<body lang="en">
|
|
<div class="subsubsection-level-extent" id="Low_002dLevel-Custom-Ports">
|
|
<div class="nav-panel">
|
|
<p>
|
|
Next: <a href="Low_002dLevel-Custom-Ports-in-C.html" accesskey="n" rel="next">Low-Level Custom Ports in C</a>, Previous: <a href="Void-Ports.html" accesskey="p" rel="prev">Void Ports</a>, Up: <a href="Port-Types.html" accesskey="u" rel="up">Types of Port</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html" title="Index" rel="index">Index</a>]</p>
|
|
</div>
|
|
<hr>
|
|
<h4 class="subsubsection" id="Low_002dLevel-Custom-Ports-1"><span>6.12.10.7 Low-Level Custom Ports<a class="copiable-link" href="#Low_002dLevel-Custom-Ports-1"> ¶</a></span></h4>
|
|
|
|
<p>This section describes how to implement a new kind of port using Guile’s
|
|
lowest-level, most primitive interfaces. First, load the <code class="code">(ice-9
|
|
custom-ports)</code> module:
|
|
</p>
|
|
<div class="example">
|
|
<pre class="example-preformatted">(use-modules (ice-9 custom-ports))
|
|
</pre></div>
|
|
|
|
<p>Then to make a new port, call <code class="code">make-custom-port</code>:
|
|
</p>
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-make_002dcustom_002dport"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">make-custom-port</strong> <var class="def-var-arguments">[#:read] [#:write] [#:read-wait-fd] [#:write-wait-fd] [#:input-waiting?] [#:seek] [#:random-access?] [#:get-natural-buffer-sizes] [#:id] [#:print] [#:close] [#:close-on-gc?] [#:truncate] [#:encoding] [#:conversion-strategy]</var><a class="copiable-link" href="#index-make_002dcustom_002dport"> ¶</a></span></dt>
|
|
<dd><p>Make a new custom port.
|
|
</p>
|
|
<p>See <a class="xref" href="Encoding.html">Encoding</a>, for more on <code class="code">#:encoding</code> and
|
|
<code class="code">#:conversion-strategy</code>.
|
|
</p></dd></dl>
|
|
|
|
<p>A port has a number of associated procedures and properties which
|
|
collectively implement its behavior. Creating a new custom port mostly
|
|
involves writing these procedures, which are passed as keyword arguments
|
|
to <code class="code">make-custom-port</code>.
|
|
</p>
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-_0023_003aread"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:read</strong> <var class="def-var-arguments">port dst start count</var><a class="copiable-link" href="#index-_0023_003aread"> ¶</a></span></dt>
|
|
<dd><p>A port’s <code class="code">#:read</code> implementation fills read buffers. It should
|
|
copy bytes to the supplied bytevector <var class="var">dst</var>, starting at offset
|
|
<var class="var">start</var> and continuing for <var class="var">count</var> bytes, and return the number
|
|
of bytes that were read, or <code class="code">#f</code> to indicate that reading any bytes
|
|
would block.
|
|
</p></dd></dl>
|
|
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-_0023_003awrite"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:write</strong> <var class="def-var-arguments">port src start count</var><a class="copiable-link" href="#index-_0023_003awrite"> ¶</a></span></dt>
|
|
<dd><p>A port’s <code class="code">#:write</code> implementation flushes write buffers to the
|
|
mutable store. It should write out bytes from the supplied bytevector
|
|
<var class="var">src</var>, starting at offset <var class="var">start</var> and continuing for <var class="var">count</var>
|
|
bytes, and return the number of bytes that were written, or <code class="code">#f</code> to
|
|
indicate writing any bytes would block.
|
|
</p></dd></dl>
|
|
|
|
<p>If <code class="code">make-custom-port</code> is passed a <code class="code">#:read</code> argument, the port
|
|
will be an input port. Passing a <code class="code">#:write</code> argument will make an
|
|
output port, and passing both will make an input-output port.
|
|
</p>
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-_0023_003aread_002dwait_002dfd"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:read-wait-fd</strong> <var class="def-var-arguments">port</var><a class="copiable-link" href="#index-_0023_003aread_002dwait_002dfd"> ¶</a></span></dt>
|
|
<dt class="deffnx def-cmd-deffn" id="index-_0023_003awrite_002dwait_002dfd"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:write-wait-fd</strong> <var class="def-var-arguments">port</var><a class="copiable-link" href="#index-_0023_003awrite_002dwait_002dfd"> ¶</a></span></dt>
|
|
<dd><p>If a port’s <code class="code">#:read</code> or <code class="code">#:write</code> method returns <code class="code">#f</code>,
|
|
that indicates that reading or writing would block, and that Guile
|
|
should instead <code class="code">poll</code> on the file descriptor returned by the port’s
|
|
<code class="code">#:read-wait-fd</code> or <code class="code">#:write-wait-fd</code> method, respectively,
|
|
until the operation can complete. See <a class="xref" href="Non_002dBlocking-I_002fO.html">Non-Blocking I/O</a>, for a more
|
|
in-depth discussion.
|
|
</p>
|
|
<p>These methods must be implemented if the <code class="code">#:read</code> or <code class="code">#:write</code>
|
|
method can return <code class="code">#f</code>, and should return a non-negative integer
|
|
file descriptor. However they may be called explicitly by a user, for
|
|
example to determine if a port may eventually be readable or writable.
|
|
If there is no associated file descriptor with the port, they should
|
|
return <code class="code">#f</code>. The default implementation returns <code class="code">#f</code>.
|
|
</p></dd></dl>
|
|
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-_0023_003ainput_002dwaiting_003f"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:input-waiting?</strong> <var class="def-var-arguments">port</var><a class="copiable-link" href="#index-_0023_003ainput_002dwaiting_003f"> ¶</a></span></dt>
|
|
<dd><p>In rare cases it is useful to be able to know whether data can be read
|
|
from a port. For example, if the user inputs <code class="code">1 2 3</code> at the
|
|
interactive console, after reading and evaluating <code class="code">1</code> the console
|
|
shouldn’t then print another prompt before reading and evaluating
|
|
<code class="code">2</code> because there is input already waiting. If the port can look
|
|
ahead, then it should implement the <code class="code">#:input-waiting?</code> method,
|
|
which returns <code class="code">#t</code> if input is available, or <code class="code">#f</code> reading the
|
|
next byte would block. The default implementation returns <code class="code">#t</code>.
|
|
</p></dd></dl>
|
|
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-_0023_003aseek"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:seek</strong> <var class="def-var-arguments">port offset whence</var><a class="copiable-link" href="#index-_0023_003aseek"> ¶</a></span></dt>
|
|
<dd><p>Set or get the current byte position of the port. Guile will flush read
|
|
and/or write buffers before seeking, as appropriate. The <var class="var">offset</var>
|
|
and <var class="var">whence</var> parameters are as for the <code class="code">seek</code> procedure;
|
|
See <a class="xref" href="Random-Access.html">Random Access</a>.
|
|
</p>
|
|
<p>The <code class="code">#:seek</code> method returns the byte position after seeking. To
|
|
query the current position, <code class="code">#:seek</code> will be called with an
|
|
<var class="var">offset</var> of 0 and <code class="code">SEEK_CUR</code> for <var class="var">whence</var>. Other values of
|
|
<var class="var">offset</var> and/or <var class="var">whence</var> will actually perform the seek. The
|
|
<code class="code">#:seek</code> method should throw an error if the port is not seekable,
|
|
which is what the default implementation does.
|
|
</p></dd></dl>
|
|
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-_0023_003atruncate"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:truncate</strong> <var class="def-var-arguments">port</var><a class="copiable-link" href="#index-_0023_003atruncate"> ¶</a></span></dt>
|
|
<dd><p>Truncate the port data to be specified length. Guile will flush buffers
|
|
beforehand, as appropriate. The default implementation throws an error,
|
|
indicating that truncation is not supported for this port.
|
|
</p></dd></dl>
|
|
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-_0023_003arandom_002daccess_003f"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:random-access?</strong> <var class="def-var-arguments">port</var><a class="copiable-link" href="#index-_0023_003arandom_002daccess_003f"> ¶</a></span></dt>
|
|
<dd><p>Return <code class="code">#t</code> if <var class="var">port</var> is open for random access, or <code class="code">#f</code>
|
|
otherwise.
|
|
</p>
|
|
<a class="index-entry-id" id="index-random-access"></a>
|
|
<p>Seeking on a random-access port with buffered input, or switching to
|
|
writing after reading, will cause the buffered input to be discarded and
|
|
Guile will seek the port back the buffered number of bytes. Likewise
|
|
seeking on a random-access port with buffered output, or switching to
|
|
reading after writing, will flush pending bytes with a call to the
|
|
<code class="code">write</code> procedure. See <a class="xref" href="Buffering.html">Buffering</a>.
|
|
</p>
|
|
<p>Indicate to Guile that your port needs this behavior by returning true
|
|
from your <code class="code">#:random-access?</code> method. The default implementation of
|
|
this function returns <code class="code">#t</code> if the port has a <code class="code">#:seek</code>
|
|
implementation.
|
|
</p></dd></dl>
|
|
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-_0023_003aget_002dnatural_002dbuffer_002dsizes"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:get-natural-buffer-sizes</strong> <var class="def-var-arguments">read-buf-size write-buf-size</var><a class="copiable-link" href="#index-_0023_003aget_002dnatural_002dbuffer_002dsizes"> ¶</a></span></dt>
|
|
<dd><p>Guile will internally attach buffers to ports. An input port always has
|
|
a read buffer, and an output port always has a write buffer.
|
|
See <a class="xref" href="Buffering.html">Buffering</a>. A port buffer consists of a bytevector, along with
|
|
some cursors into that bytevector denoting where to get and put data.
|
|
</p>
|
|
<p>Port implementations generally don’t have to be concerned with
|
|
buffering: a port’s <code class="code">#:read</code> or <code class="code">#:write</code> method will receive
|
|
the buffer’s bytevector as an argument, along with an offset and a
|
|
length into that bytevector, and should then either fill or empty that
|
|
bytevector. However in some cases, port implementations may be able to
|
|
provide an appropriate default buffer size to Guile. For example file
|
|
ports implement <code class="code">#:get-natural-buffer-sizes</code> to let the operating
|
|
system inform Guile about the appropriate buffer sizes for the
|
|
particular file opened by the port.
|
|
</p>
|
|
<p>This method returns two values, corresponding to the natural read and
|
|
write buffer sizes for the ports. The two parameters
|
|
<var class="var">read-buf-size</var> and <var class="var">write-buf-size</var> are Guile’s guesses for
|
|
what sizes might be good. A custom <code class="code">#:get-natural-buffer-sizes</code>
|
|
method could override Guile’s choices, or just pass them on, as the
|
|
default implementation does.
|
|
</p></dd></dl>
|
|
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-_0023_003aprint"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:print</strong> <var class="def-var-arguments">port out</var><a class="copiable-link" href="#index-_0023_003aprint"> ¶</a></span></dt>
|
|
<dd><p>Called when the port <var class="var">port</var> is written to <var class="var">out</var>, e.g. via
|
|
<code class="code">(write port out)</code>.
|
|
</p>
|
|
<p>If <code class="code">#:print</code> is not explicitly supplied, the default implementation
|
|
prints something like <code class="code">#<<var class="var">mode</var>:<var class="var">id</var> <var class="var">address</var>></code>, where
|
|
<var class="var">mode</var> is either <code class="code">input</code>, <code class="code">output</code>, or
|
|
<code class="code">input-output</code>, <var class="var">id</var> comes from the <code class="code">#:id</code> keyword
|
|
argument (defaulting to <code class="code">"custom-port"</code>), and <var class="var">address</var> is a
|
|
unique integer associated with the port.
|
|
</p></dd></dl>
|
|
|
|
<dl class="first-deffn">
|
|
<dt class="deffn" id="index-_0023_003aclose"><span class="category-def">Scheme Port Method: </span><span><strong class="def-name">#:close</strong> <var class="def-var-arguments">port</var><a class="copiable-link" href="#index-_0023_003aclose"> ¶</a></span></dt>
|
|
<dd><p>Called when <var class="var">port</var> is closed. It should release any
|
|
explicitly-managed resources used by the port.
|
|
</p></dd></dl>
|
|
|
|
<p>By default, ports that are garbage collected just go away without
|
|
closing or flushing any buffered output. If your port needs to release
|
|
some external resource like a file descriptor, or needs to make sure
|
|
that its internal buffers are flushed even if the port is collected
|
|
while it was open, then pass <code class="code">#:close-on-gc? #t</code> to
|
|
<code class="code">make-custom-port</code>. Note that in that case, the <code class="code">#:close</code>
|
|
method will probably be called on a separate thread.
|
|
</p>
|
|
<p>Note that calls to all of these methods can proceed in parallel and
|
|
concurrently and from any thread up until the point that the port is
|
|
closed. The call to <code class="code">close</code> will happen when no other method is
|
|
running, and no method will be called after the <code class="code">close</code> method is
|
|
called. If your port implementation needs mutual exclusion to prevent
|
|
concurrency, it is responsible for locking appropriately.
|
|
</p>
|
|
</div>
|
|
<hr>
|
|
<div class="nav-panel">
|
|
<p>
|
|
Next: <a href="Low_002dLevel-Custom-Ports-in-C.html">Low-Level Custom Ports in C</a>, Previous: <a href="Void-Ports.html">Void Ports</a>, Up: <a href="Port-Types.html">Types of Port</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html" title="Index" rel="index">Index</a>]</p>
|
|
</div>
|
|
|
|
|
|
|
|
</body>
|
|
</html>
|