226 lines
13 KiB
HTML
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> [<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"> ¶</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->bytevector</strong> <var class="def-var-arguments">pointer len [offset [uvec_type]]</var><a class="copiable-link" href="#index-pointer_002d_003ebytevector"> ¶</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"> ¶</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->pointer</strong> <var class="def-var-arguments">bv [offset]</var><a class="copiable-link" href="#index-bytevector_002d_003epointer"> ¶</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"> ¶</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"> ¶</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->pointer</strong> <var class="def-var-arguments">string [encoding]</var><a class="copiable-link" href="#index-string_002d_003epointer"> ¶</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->string</strong> <var class="def-var-arguments">pointer [length] [encoding]</var><a class="copiable-link" href="#index-pointer_002d_003estring"> ¶</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"> ¶</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>)) ⇒ #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 "#<bottle of ~a ~x>"
|
|
(bottle-contents b)
|
|
(pointer-address (unwrap-bottle b)))))
|
|
|
|
(define grab-bottle
|
|
;; Wrapper for `bottle_t *grab (void)'.
|
|
(let ((grab (foreign-library-function libbottle "grab_bottle"
|
|
#:return-type '*)))
|
|
(lambda ()
|
|
"Return a new bottle."
|
|
(wrap-bottle (grab)))))
|
|
|
|
(define bottle-contents
|
|
;; Wrapper for `const char *bottle_contents (bottle_t *)'.
|
|
(let ((contents (foreign-library-function libbottle "bottle_contents"
|
|
#:return-type '*
|
|
#:arg-types '(*))))
|
|
(lambda (b)
|
|
"Return the contents of B."
|
|
(pointer->string (contents (unwrap-bottle b))))))
|
|
|
|
(write (grab-bottle))
|
|
⇒ #<bottle of Château Haut-Brion 803d36>
|
|
</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 "scm_numptob"))
|
|
numptob
|
|
(bytevector-uint-ref (pointer->bytevector numptob (sizeof long))
|
|
0 (native-endianness)
|
|
(sizeof long))
|
|
⇒ 8
|
|
</pre></div>
|
|
|
|
<p>If we wanted to corrupt Guile’s internal state, we could set
|
|
<code class="code">scm_numptob</code> to another value; but we shouldn’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> [<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>
|