1
0
Fork 0
cl-sites/guile.html_node/Low_002dLevel-Custom-Ports-in-C.html

141 lines
13 KiB
HTML
Raw Normal View History

2024-12-17 12:49:28 +01:00
<!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 in C (Guile Reference Manual)</title>
<meta name="description" content="Low-Level Custom Ports in C (Guile Reference Manual)">
<meta name="keywords" content="Low-Level Custom Ports in C (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.html" rel="prev" title="Low-Level Custom Ports">
<style type="text/css">
<!--
a.copiable-link {visibility: hidden; text-decoration: none; line-height: 0em}
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-in-C">
<div class="nav-panel">
<p>
Previous: <a href="Low_002dLevel-Custom-Ports.html" accesskey="p" rel="prev">Low-Level Custom Ports</a>, Up: <a href="Port-Types.html" accesskey="u" rel="up">Types of Port</a> &nbsp; [<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-in-C-1"><span>6.12.10.8 Low-Level Custom Ports in C<a class="copiable-link" href="#Low_002dLevel-Custom-Ports-in-C-1"> &para;</a></span></h4>
<p>The <code class="code">make-custom-port</code> procedure described in the previous section
has similar functionality on the C level, though it is organized a bit
differently.
</p>
<p>In C, the mechanism is that one creates a new <em class="dfn">port type object</em>.
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.
</p>
<p>Ports themselves have associated <em class="dfn">stream</em> values. The stream is a
pointer controlled by the user, which is set when the port is created.
Given a port, the <code class="code">SCM_STREAM</code> macro returns its associated stream
value, as a <code class="code">scm_t_bits</code>. 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&rsquo;t
need access to the stream because the <code class="code">make-custom-port</code> methods
can be closures that share port-specific data directly.
</p>
<p>A port type is created by calling <code class="code">scm_make_port_type</code>.
</p>
<dl class="first-deftypefn first-deftypefun-alias-first-deftypefn">
<dt class="deftypefn deftypefun-alias-deftypefn" id="index-scm_005fmake_005fport_005ftype"><span class="category-def">Function: </span><span><code class="def-type">scm_t_port_type*</code> <strong class="def-name">scm_make_port_type</strong> <code class="def-code-arguments">(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))</code><a class="copiable-link" href="#index-scm_005fmake_005fport_005ftype"> &para;</a></span></dt>
<dd><p>Define a new port type. The <var class="var">name</var> parameter is like the
<code class="code">#:id</code> parameter to <code class="code">make-custom-port</code>; and <var class="var">read</var> and
<var class="var">write</var> are like <code class="code">make-custom-port</code>&rsquo;s <code class="code">#:read</code> and
<code class="code">#:write</code>, except that they should return <code class="code">(size_t)-1</code> if the
read or write operation would block, instead of <code class="code">#f</code>.
</p></dd></dl>
<dl class="first-deftypefn first-deftypefun-alias-first-deftypefn">
<dt class="deftypefn deftypefun-alias-deftypefn" id="index-scm_005fset_005fport_005fread_005fwait_005ffd"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_set_port_read_wait_fd</strong> <code class="def-code-arguments">(scm_t_port_type *type, int (*wait_fd) (SCM port))</code><a class="copiable-link" href="#index-scm_005fset_005fport_005fread_005fwait_005ffd"> &para;</a></span></dt>
<dt class="deftypefnx deftypefunx-alias-deftypefnx def-cmd-deftypefn" id="index-scm_005fset_005fport_005fwrite_005fwait_005ffd"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_set_port_write_wait_fd</strong> <code class="def-code-arguments">(scm_t_port_type *type, int (*wait_fd) (SCM port))</code><a class="copiable-link" href="#index-scm_005fset_005fport_005fwrite_005fwait_005ffd"> &para;</a></span></dt>
<dt class="deftypefnx deftypefunx-alias-deftypefnx def-cmd-deftypefn" id="index-scm_005fset_005fport_005fprint"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_set_port_print</strong> <code class="def-code-arguments">(scm_t_port_type *type, int (*print) (SCM port, SCM dest_port, scm_print_state *pstate))</code><a class="copiable-link" href="#index-scm_005fset_005fport_005fprint"> &para;</a></span></dt>
<dt class="deftypefnx deftypefunx-alias-deftypefnx def-cmd-deftypefn" id="index-scm_005fset_005fport_005fclose"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_set_port_close</strong> <code class="def-code-arguments">(scm_t_port_type *type, void (*close) (SCM port))</code><a class="copiable-link" href="#index-scm_005fset_005fport_005fclose"> &para;</a></span></dt>
<dt class="deftypefnx deftypefunx-alias-deftypefnx def-cmd-deftypefn" id="index-scm_005fset_005fport_005fneeds_005fclose_005fon_005fgc"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_set_port_needs_close_on_gc</strong> <code class="def-code-arguments">(scm_t_port_type *type, int needs_close_p)</code><a class="copiable-link" href="#index-scm_005fset_005fport_005fneeds_005fclose_005fon_005fgc"> &para;</a></span></dt>
<dt class="deftypefnx deftypefunx-alias-deftypefnx def-cmd-deftypefn" id="index-scm_005fset_005fport_005fseek"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_set_port_seek</strong> <code class="def-code-arguments">(scm_t_port_type *type, scm_t_off (*seek) (SCM port, scm_t_off offset, int whence))</code><a class="copiable-link" href="#index-scm_005fset_005fport_005fseek"> &para;</a></span></dt>
<dt class="deftypefnx deftypefunx-alias-deftypefnx def-cmd-deftypefn" id="index-scm_005fset_005fport_005ftruncate"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_set_port_truncate</strong> <code class="def-code-arguments">(scm_t_port_type *type, void (*truncate) (SCM port, scm_t_off length))</code><a class="copiable-link" href="#index-scm_005fset_005fport_005ftruncate"> &para;</a></span></dt>
<dt class="deftypefnx deftypefunx-alias-deftypefnx def-cmd-deftypefn" id="index-scm_005fset_005fport_005frandom_005faccess_005fp"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_set_port_random_access_p</strong> <code class="def-code-arguments">(scm_t_port_type *type, int (*random_access_p) (SCM port));</code><a class="copiable-link" href="#index-scm_005fset_005fport_005frandom_005faccess_005fp"> &para;</a></span></dt>
<dt class="deftypefnx deftypefunx-alias-deftypefnx def-cmd-deftypefn" id="index-scm_005fset_005fport_005finput_005fwaiting"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_set_port_input_waiting</strong> <code class="def-code-arguments">(scm_t_port_type *type, int (*input_waiting) (SCM port));</code><a class="copiable-link" href="#index-scm_005fset_005fport_005finput_005fwaiting"> &para;</a></span></dt>
<dt class="deftypefnx deftypefunx-alias-deftypefnx def-cmd-deftypefn" id="index-scm_005fset_005fport_005fget_005fnatural_005fbuffer_005fsizes"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_set_port_get_natural_buffer_sizes</strong> <code class="def-code-arguments">(scm_t_port_type *type, void (*get_natural_buffer_sizes) (SCM, size_t *read_buf_size, size_t *write_buf_size))</code><a class="copiable-link" href="#index-scm_005fset_005fport_005fget_005fnatural_005fbuffer_005fsizes"> &para;</a></span></dt>
<dd><p>Port method definitions. See <a class="xref" href="Low_002dLevel-Custom-Ports.html">Low-Level Custom Ports</a>, for more
details on each of these methods.
</p></dd></dl>
<p>Once you have your port type, you can create ports with
<code class="code">scm_c_make_port</code>, or <code class="code">scm_c_make_port_with_encoding</code>.
</p>
<dl class="first-deftypefn first-deftypefun-alias-first-deftypefn">
<dt class="deftypefn deftypefun-alias-deftypefn" id="index-scm_005fc_005fmake_005fport_005fwith_005fencoding"><span class="category-def">Function: </span><span><code class="def-type">SCM</code> <strong class="def-name">scm_c_make_port_with_encoding</strong> <code class="def-code-arguments">(scm_t_port_type *type, unsigned long mode_bits, SCM encoding, SCM conversion_strategy, scm_t_bits stream)</code><a class="copiable-link" href="#index-scm_005fc_005fmake_005fport_005fwith_005fencoding"> &para;</a></span></dt>
<dt class="deftypefnx deftypefunx-alias-deftypefnx def-cmd-deftypefn" id="index-scm_005fc_005fmake_005fport"><span class="category-def">Function: </span><span><code class="def-type">SCM</code> <strong class="def-name">scm_c_make_port</strong> <code class="def-code-arguments">(scm_t_port_type *type, unsigned long mode_bits, scm_t_bits stream)</code><a class="copiable-link" href="#index-scm_005fc_005fmake_005fport"> &para;</a></span></dt>
<dd><p>Make a port with the given <var class="var">type</var>. The <var class="var">stream</var> indicates the
private data associated with the port, which your port implementation
may later retrieve with <code class="code">SCM_STREAM</code>. The mode bits should include
one or more of the flags <code class="code">SCM_RDNG</code> or <code class="code">SCM_WRTNG</code>, indicating
that the port is an input and/or an output port, respectively. The mode
bits may also include <code class="code">SCM_BUF0</code> or <code class="code">SCM_BUFLINE</code>, indicating
that the port should be unbuffered or line-buffered, respectively. The
default is that the port will be block-buffered. See <a class="xref" href="Buffering.html">Buffering</a>.
</p>
<p>As you would imagine, <var class="var">encoding</var> and <var class="var">conversion_strategy</var>
specify the port&rsquo;s initial textual encoding and conversion strategy.
Both are symbols. <code class="code">scm_c_make_port</code> is the same as
<code class="code">scm_c_make_port_with_encoding</code>, except it uses the default port
encoding and conversion strategy.
</p></dd></dl>
<p>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&rsquo;s <code class="code">make-custom-port</code>. The speed is similar between C and
Scheme, and ports implemented in C have the disadvantage of not being
suspendable. See <a class="xref" href="Non_002dBlocking-I_002fO.html">Non-Blocking I/O</a>.
</p>
</div>
<hr>
<div class="nav-panel">
<p>
Previous: <a href="Low_002dLevel-Custom-Ports.html">Low-Level Custom Ports</a>, Up: <a href="Port-Types.html">Types of Port</a> &nbsp; [<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>