1
0
Fork 0
cl-sites/guile.html_node/Foreign-Objects-and-Scheme.html
2024-12-17 12:49:28 +01:00

187 lines
8.8 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>Foreign Objects and Scheme (Guile Reference Manual)</title>
<meta name="description" content="Foreign Objects and Scheme (Guile Reference Manual)">
<meta name="keywords" content="Foreign Objects and Scheme (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="Defining-New-Foreign-Object-Types.html" rel="up" title="Defining New Foreign Object Types">
<link href="Foreign-Object-Memory-Management.html" rel="prev" title="Foreign Object Memory Management">
<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}
-->
</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="Foreign-Objects-and-Scheme">
<div class="nav-panel">
<p>
Previous: <a href="Foreign-Object-Memory-Management.html" accesskey="p" rel="prev">Foreign Object Memory Management</a>, Up: <a href="Defining-New-Foreign-Object-Types.html" accesskey="u" rel="up">Defining New Foreign Object Types</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="Foreign-Objects-and-Scheme-1"><span>5.5.5 Foreign Objects and Scheme<a class="copiable-link" href="#Foreign-Objects-and-Scheme-1"> &para;</a></span></h4>
<p>It is also possible to create foreign objects and object types from
Scheme, and to access fields of foreign objects from Scheme. For
example, the file example from the last section could be equivalently
expressed as:
</p>
<div class="example">
<pre class="example-preformatted">(define-module (my-file)
#:use-module (system foreign-object)
#:use-module ((oop goops) #:select (make))
#:export (make-file))
(define (finalize-file file)
(let ((fd (struct-ref file 0)))
(unless (&lt; fd 0)
(struct-set! file 0 -1)
(close-fdes fd))))
(define &lt;file&gt;
(make-foreign-object-type '&lt;file&gt; '(fd)
#:finalizer finalize-file))
(define (make-file fd)
(make &lt;file&gt; #:fd fd))
</pre></div>
<p>Here we see that the result of <code class="code">make-foreign-object-type</code>, which is
the equivalent of <code class="code">scm_make_foreign_object_type</code>, is a struct
vtable. See <a class="xref" href="Vtables.html">Vtables</a>, for more information. To instantiate the
foreign object, which is really a Guile struct, we use <code class="code">make</code>. (We
could have used <code class="code">make-struct/no-tail</code>, but as an implementation
detail, finalizers are attached in the <code class="code">initialize</code> method called
by <code class="code">make</code>). To access the fields, we use <code class="code">struct-ref</code> and
<code class="code">struct-set!</code>. See <a class="xref" href="Structure-Basics.html">Structure Basics</a>.
</p>
<p>There is a convenience syntax, <code class="code">define-foreign-object-type</code>, that
defines a type along with a constructor, and getters for the fields. An
appropriate invocation of <code class="code">define-foreign-object-type</code> for the
file object type could look like this:
</p>
<div class="example">
<pre class="example-preformatted">(use-modules (system foreign-object))
(define-foreign-object-type &lt;file&gt;
make-file
(fd)
#:finalizer finalize-file)
</pre></div>
<p>This defines the <code class="code">&lt;file&gt;</code> type with one field, a <code class="code">make-file</code>
constructor, and a getter for the <code class="code">fd</code> field, bound to <code class="code">fd</code>.
</p>
<p>Foreign object types are not only vtables but are actually GOOPS
classes, as hinted at above. See <a class="xref" href="GOOPS.html">GOOPS</a>, for more on Guile&rsquo;s
object-oriented programming system. Thus one can define print and
equality methods using GOOPS:
</p>
<div class="example">
<pre class="example-preformatted">(use-modules (oop goops))
(define-method (write (file &lt;file&gt;) port)
;; Assuming existence of the `fd' getter
(format port &quot;#&lt;&lt;file&gt; ~a&gt;&quot; (fd file)))
(define-method (equal? (a &lt;file&gt;) (b &lt;file&gt;))
(eqv? (fd a) (fd b)))
</pre></div>
<p>One can even sub-class foreign types.
</p>
<div class="example">
<pre class="example-preformatted">(define-class &lt;named-file&gt; (&lt;file&gt;)
(name #:init-keyword #:name #:init-value #f #:accessor name))
</pre></div>
<p>The question arises of how to construct these values, given that
<code class="code">make-file</code> returns a plain old <code class="code">&lt;file&gt;</code> object. It turns out
that you can use the GOOPS construction interface, where every field of
the foreign object has an associated initialization keyword argument.
</p>
<div class="example">
<pre class="example-preformatted">(define* (my-open-file name #:optional (flags O_RDONLY))
(make &lt;named-file&gt; #:fd (open-fdes name flags) #:name name))
(define-method (write (file &lt;named-file&gt;) port)
(format port &quot;#&lt;&lt;file&gt; ~s ~a&gt;&quot; (name file) (fd file)))
</pre></div>
<p>See <a class="xref" href="Foreign-Objects.html">Foreign Objects</a>, for full documentation on the Scheme interface
to foreign objects. See <a class="xref" href="GOOPS.html">GOOPS</a>, for more on GOOPS.
</p>
<p>As a final note, you might wonder how this system supports encapsulation
of sensitive values. First, we have to recognize that some facilities
are essentially unsafe and have global scope. For example, in C, the
integrity and confidentiality of a part of a program is at the mercy of
every other part of that program &ndash; because any part of the program can
read and write anything in its address space. At the same time,
principled access to structured data is organized in C on lexical
boundaries; if you don&rsquo;t expose accessors for your object, you trust
other parts of the program not to work around that barrier.
</p>
<p>The situation is not dissimilar in Scheme. Although Scheme&rsquo;s unsafe
constructs are fewer in number than in C, they do exist. The
<code class="code">(system foreign)</code> module can be used to violate confidentiality
and integrity, and shouldn&rsquo;t be exposed to untrusted code. Although
<code class="code">struct-ref</code> and <code class="code">struct-set!</code> are less unsafe, they still
have a cross-cutting capability of drilling through abstractions.
Performing a <code class="code">struct-set!</code> on a foreign object slot could cause
unsafe foreign code to crash. Ultimately, structures in Scheme are
capabilities for abstraction, and not abstractions themselves.
</p>
<p>That leaves us with the lexical capabilities, like constructors and
accessors. Here is where encapsulation lies: the practical degree to
which the innards of your foreign objects are exposed is the degree to
which their accessors are lexically available in user code. If you want
to allow users to reference fields of your foreign object, provide them
with a getter. Otherwise you should assume that the only access to your
object may come from your code, which has the relevant authority, or via
code with access to cross-cutting <code class="code">struct-ref</code> and such, which also
has the cross-cutting authority.
</p>
</div>
<hr>
<div class="nav-panel">
<p>
Previous: <a href="Foreign-Object-Memory-Management.html">Foreign Object Memory Management</a>, Up: <a href="Defining-New-Foreign-Object-Types.html">Defining New Foreign Object Types</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>