1
0
Fork 0
cl-sites/guile.html_node/Void-Pointers-and-Byte-Access.html
2024-12-17 12:49:28 +01:00

226 lines
13 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>Void Pointers and Byte Access (Guile Reference Manual)</title>
<meta name="description" content="Void Pointers and Byte Access (Guile Reference Manual)">
<meta name="keywords" content="Void Pointers and Byte Access (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="Foreign-Function-Interface.html" rel="up" title="Foreign Function Interface">
<link href="Foreign-Structs.html" rel="next" title="Foreign Structs">
<link href="Foreign-Functions.html" rel="prev" title="Foreign Functions">
<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}
ul.mark-bullet {list-style-type: disc}
-->
</style>
<link rel="stylesheet" type="text/css" href="https://www.gnu.org/software/gnulib/manual.css">
</head>
<body lang="en">
<div class="subsection-level-extent" id="Void-Pointers-and-Byte-Access">
<div class="nav-panel">
<p>
Next: <a href="Foreign-Structs.html" accesskey="n" rel="next">Foreign Structs</a>, Previous: <a href="Foreign-Functions.html" accesskey="p" rel="prev">Foreign Functions</a>, Up: <a href="Foreign-Function-Interface.html" accesskey="u" rel="up">Foreign Function Interface</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="subsection" id="Void-Pointers-and-Byte-Access-1"><span>6.19.6 Void Pointers and Byte Access<a class="copiable-link" href="#Void-Pointers-and-Byte-Access-1"> &para;</a></span></h4>
<p>Wrapped pointers are untyped, so they are essentially equivalent to C
<code class="code">void</code> pointers. As in C, the memory region pointed to by a
pointer can be accessed at the byte level. This is achieved using
<em class="emph">bytevectors</em> (see <a class="pxref" href="Bytevectors.html">Bytevectors</a>). The <code class="code">(rnrs bytevectors)</code>
module contains procedures that can be used to convert byte sequences to
Scheme objects such as strings, floating point numbers, or integers.
</p>
<p>Load the <code class="code">(system foreign)</code> module to use these Scheme interfaces.
</p>
<div class="example">
<pre class="example-preformatted">(use-modules (system foreign))
</pre></div>
<dl class="first-deffn">
<dt class="deffn" id="index-pointer_002d_003ebytevector"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">pointer-&gt;bytevector</strong> <var class="def-var-arguments">pointer len [offset [uvec_type]]</var><a class="copiable-link" href="#index-pointer_002d_003ebytevector"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fpointer_005fto_005fbytevector"><span class="category-def">C Function: </span><span><strong class="def-name">scm_pointer_to_bytevector</strong> <var class="def-var-arguments">(pointer, len, offset, uvec_type)</var><a class="copiable-link" href="#index-scm_005fpointer_005fto_005fbytevector"> &para;</a></span></dt>
<dd><p>Return a bytevector aliasing the <var class="var">len</var> bytes pointed to by
<var class="var">pointer</var>.
</p>
<p>The user may specify an alternate default interpretation for the memory
by passing the <var class="var">uvec_type</var> argument, to indicate that the memory is
an array of elements of that type. <var class="var">uvec_type</var> should be something
that <code class="code">array-type</code> would return, like <code class="code">f32</code> or <code class="code">s16</code>.
</p>
<p>When <var class="var">offset</var> is passed, it specifies the offset in bytes relative
to <var class="var">pointer</var> of the memory region aliased by the returned
bytevector.
</p>
<p>Mutating the returned bytevector mutates the memory pointed to by
<var class="var">pointer</var>, so buckle your seatbelts.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-bytevector_002d_003epointer"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">bytevector-&gt;pointer</strong> <var class="def-var-arguments">bv [offset]</var><a class="copiable-link" href="#index-bytevector_002d_003epointer"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fbytevector_005fto_005fpointer"><span class="category-def">C Function: </span><span><strong class="def-name">scm_bytevector_to_pointer</strong> <var class="def-var-arguments">(bv, offset)</var><a class="copiable-link" href="#index-scm_005fbytevector_005fto_005fpointer"> &para;</a></span></dt>
<dd><p>Return a pointer aliasing the memory pointed to by <var class="var">bv</var> or
<var class="var">offset</var> bytes after <var class="var">bv</var> when <var class="var">offset</var> is passed.
</p></dd></dl>
<p>In addition to these primitives, convenience procedures are available:
</p>
<dl class="first-deffn">
<dt class="deffn" id="index-dereference_002dpointer"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">dereference-pointer</strong> <var class="def-var-arguments">pointer</var><a class="copiable-link" href="#index-dereference_002dpointer"> &para;</a></span></dt>
<dd><p>Assuming <var class="var">pointer</var> points to a memory region that holds a pointer,
return this pointer.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-string_002d_003epointer"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">string-&gt;pointer</strong> <var class="def-var-arguments">string [encoding]</var><a class="copiable-link" href="#index-string_002d_003epointer"> &para;</a></span></dt>
<dd><p>Return a foreign pointer to a nul-terminated copy of <var class="var">string</var> in the
given <var class="var">encoding</var>, defaulting to the current locale encoding. The C
string is freed when the returned foreign pointer becomes unreachable.
</p>
<p>This is the Scheme equivalent of <code class="code">scm_to_stringn</code>.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-pointer_002d_003estring"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">pointer-&gt;string</strong> <var class="def-var-arguments">pointer [length] [encoding]</var><a class="copiable-link" href="#index-pointer_002d_003estring"> &para;</a></span></dt>
<dd><p>Return the string representing the C string pointed to by <var class="var">pointer</var>.
If <var class="var">length</var> is omitted or <code class="code">-1</code>, the string is assumed to be
nul-terminated. Otherwise <var class="var">length</var> is the number of bytes in memory
pointed to by <var class="var">pointer</var>. The C string is assumed to be in the given
<var class="var">encoding</var>, defaulting to the current locale encoding.
</p>
<p>This is the Scheme equivalent of <code class="code">scm_from_stringn</code>.
</p></dd></dl>
<a class="index-entry-id" id="index-wrapped-pointer-types"></a>
<p>Most object-oriented C libraries use pointers to specific data
structures to identify objects. It is useful in such cases to reify the
different pointer types as disjoint Scheme types. The
<code class="code">define-wrapped-pointer-type</code> macro simplifies this.
</p>
<dl class="first-deffn">
<dt class="deffn" id="index-define_002dwrapped_002dpointer_002dtype"><span class="category-def">Scheme Syntax: </span><span><strong class="def-name">define-wrapped-pointer-type</strong> <var class="def-var-arguments">type-name pred wrap unwrap print</var><a class="copiable-link" href="#index-define_002dwrapped_002dpointer_002dtype"> &para;</a></span></dt>
<dd><p>Define helper procedures to wrap pointer objects into Scheme objects
with a disjoint type. Specifically, this macro defines:
</p>
<ul class="itemize mark-bullet">
<li><var class="var">pred</var>, a predicate for the new Scheme type;
</li><li><var class="var">wrap</var>, a procedure that takes a pointer object and returns an
object that satisfies <var class="var">pred</var>;
</li><li><var class="var">unwrap</var>, which does the reverse.
</li></ul>
<p><var class="var">wrap</var> preserves pointer identity, for two pointer objects <var class="var">p1</var>
and <var class="var">p2</var> that are <code class="code">equal?</code>, <code class="code">(eq? (<var class="var">wrap</var> <var class="var">p1</var>)
(<var class="var">wrap</var> <var class="var">p2</var>)) &rArr; #t</code>.
</p>
<p>Finally, <var class="var">print</var> should name a user-defined procedure to print such
objects. The procedure is passed the wrapped object and a port to write
to.
</p>
<p>For example, assume we are wrapping a C library that defines a type,
<code class="code">bottle_t</code>, and functions that can be passed <code class="code">bottle_t *</code>
pointers to manipulate them. We could write:
</p>
<div class="example">
<pre class="example-preformatted">(define-wrapped-pointer-type bottle
bottle?
wrap-bottle unwrap-bottle
(lambda (b p)
(format p &quot;#&lt;bottle of ~a ~x&gt;&quot;
(bottle-contents b)
(pointer-address (unwrap-bottle b)))))
(define grab-bottle
;; Wrapper for `bottle_t *grab (void)'.
(let ((grab (foreign-library-function libbottle &quot;grab_bottle&quot;
#:return-type '*)))
(lambda ()
&quot;Return a new bottle.&quot;
(wrap-bottle (grab)))))
(define bottle-contents
;; Wrapper for `const char *bottle_contents (bottle_t *)'.
(let ((contents (foreign-library-function libbottle &quot;bottle_contents&quot;
#:return-type '*
#:arg-types '(*))))
(lambda (b)
&quot;Return the contents of B.&quot;
(pointer-&gt;string (contents (unwrap-bottle b))))))
(write (grab-bottle))
&rArr; #&lt;bottle of Ch&acirc;teau Haut-Brion 803d36&gt;
</pre></div>
<p>In this example, <code class="code">grab-bottle</code> is guaranteed to return a genuine
<code class="code">bottle</code> object satisfying <code class="code">bottle?</code>. Likewise,
<code class="code">bottle-contents</code> errors out when its argument is not a genuine
<code class="code">bottle</code> object.
</p></dd></dl>
<p>As another example, currently Guile has a variable, <code class="code">scm_numptob</code>,
as part of its API. It is declared as a C <code class="code">long</code>. So, to read its
value, we can do:
</p>
<div class="example">
<pre class="example-preformatted">(use-modules (system foreign))
(use-modules (rnrs bytevectors))
(define numptob
(foreign-library-pointer #f &quot;scm_numptob&quot;))
numptob
(bytevector-uint-ref (pointer-&gt;bytevector numptob (sizeof long))
0 (native-endianness)
(sizeof long))
&rArr; 8
</pre></div>
<p>If we wanted to corrupt Guile&rsquo;s internal state, we could set
<code class="code">scm_numptob</code> to another value; but we shouldn&rsquo;t, because that
variable is not meant to be set. Indeed this point applies more widely:
the C API is a dangerous place to be. Not only might setting a value
crash your program, simply accessing the data pointed to by a dangling
pointer or similar can prove equally disastrous.
</p>
</div>
<hr>
<div class="nav-panel">
<p>
Next: <a href="Foreign-Structs.html">Foreign Structs</a>, Previous: <a href="Foreign-Functions.html">Foreign Functions</a>, Up: <a href="Foreign-Function-Interface.html">Foreign Function Interface</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>