foreign-c/documentation/R7RS-PFFI.html

798 lines
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Portable Foreign Function Interface for R7RS
Documentation - 0.6.0</title>
<style>
table { width: 250%; }
nav { float: left; width: 20%;}
main { float: right; width: 80%; }
pre { background-color: lightgrey; }
</style>
</head>
<body>
<h1 id="portable-foreign-function-interface-for-r7rs">Portable
Foreign Function Interface for R7RS</h1>
<p>Portable foreign function interface for R7RS. It is portable
in the sense that it supports multiple implementations, as
opposed to being portable by conforming to some
specification.</p>
<p><a
href="https://todo.sr.ht/~retropikzel/r7rs-pffi">Project</a></p>
<p><a href="https://sr.ht/~retropikzel/r7rs-pffi/trackers">Issue
trackers</a></p>
<p><a href="https://sr.ht/~retropikzel/r7rs-pffi/lists">Maling
lists</a></p>
<p><a
href="https://jenkins.scheme.org/job/r7rs_pffi/job/r7rs-pffi/">Jenkins</a></p>
<h2 id="table-of-contents">Table of contents</h2>
<nav>
<ul>
<li><a href="#goals">Goals</a></li>
<li><a href="#non-goals">Non Goals</a></li>
<li><a href="#status">Status</a>
<ul>
<li><a href="#current-caveats">Current caveats</a></li>
</ul></li>
<li><a href="#roadmap">Roadmap</a></li>
<li><a href="#feature-implementation-table">Feature
implementation table</a>
<ul>
<li><a
href="#feature-implementation-table-primitives">Primitives</a></li>
<li><a href="#feature-implementation-table-built-upon">Built
upon</a></li>
</ul></li>
<li><a href="#documentation">Documentation</a>
<ul>
<li><a href="#dependencies">Dependencies</a>
<ul>
<li><a href="#dependencies-chibi">Chibi</a></li>
<li><a href="#dependencies-chicken">Chicken</a></li>
<li><a href="#dependencies-gauche">Gauche</a></li>
<li><a href="#dependencies-racket">Racket</a></li>
<li><a href="#dependencies-kawa">Kawa</a></li>
</ul></li>
<li><a href="#installation">Installation</a>
<ul>
<li><a href="#installation-project-local">Project local</a>
<ul>
<li><a href="#installation-project-local-linux">Linux</a></li>
<li><a
href="#installation-project-local-windows">Windows</a></li>
</ul></li>
<li><a href="#installation-system-global">System global</a></li>
</ul></li>
</ul></li>
<li><a href="#reference">Reference</a>
<ul>
<li><a href="#types">Types</a></li>
<li><a href="#environment-variables">Environment variables</a>
<ul>
<li><a
href="#environment-variables-pffi-load-path">PFFI_LOAD_PATH</a></li>
</ul></li>
<li><a href="#procedures-and-macros">Procedures and macros</a>
<ul>
<li><a href="#pffi-init">pffi-init</a></li>
<li><a href="#c-size-of">c-size-of</a></li>
<li><a href="#pffi-align-of">pffi-align-of</a></li>
<li><a href="#define-c-library">define-c-library</a></li>
<li><a href="#make-c-null">make-c-null</a></li>
<li><a href="#is-c-null">c-null?</a></li>
<li><a href="#make-c-bytevector">make-c-bytevector</a></li>
<li><a
href="#pffi-pointer-address">pffi-pointer-address</a></li>
<li><a href="#is-c-bytevector">c-bytevector?</a></li>
<li><a href="#c-free">c-free</a></li>
<li><a href="#pffi-pointer-set!">pffi-pointer-set!</a></li>
<li><a href="#pffi-pointer-get">pffi-pointer-get</a></li>
<li><a
href="#string-into-c-bytevector">string-&gt;c-bytevector</a></li>
<li><a
href="#c-bytevector-into-string">c-bytevector-&gt;sring</a></li>
<li><a href="#pffi-struct-make">pffi-struct-make</a></li>
<li><a href="#pffi-struct-pointer">pffi-struct-pointer</a></li>
<li><a
href="#pffi-struct-offset-get">pffi-struct-offset-get</a></li>
<li><a href="#pffi-struct-get">pffi-struct-get</a></li>
<li><a href="#pffi-struct-set!">pffi-struct-set!</a></li>
<li><a href="#pffi-array-allocate">pffi-array-allocate</a></li>
<li><a href="#pffi-array-pointer">pffi-array-pointer</a></li>
<li><a href="#pffi-array">pffi-array?</a></li>
<li><a
href="#pffi-pointer-%3Earray">pffi-pointer-&gt;array</a></li>
<li><a href="#pffi-array-get">pffi-array-get</a></li>
<li><a href="#pffi-array-set!">pffi-array-set!</a></li>
<li><a href="#pffi-list-%3Earray">pffi-list-&gt;array</a></li>
<li><a href="#pffi-array-%3Elist">pffi-array-&gt;list</a></li>
<li><a href="#define-c-procedure">define-c-procedure</a></li>
<li><a
href="#pffi-define-callback">pffi-define-callback</a></li>
</ul></li>
</ul></li>
</ul>
</nav>
<main>
<h2 id="goals">Goals</h2>
<p><a name="goals"></a></p>
<ul>
<li>Support only R7RS implementations</li>
<li>Same interface on all implementations
<ul>
<li>Some things that are procedures on one implementation are
macros on other, but they must behave the same</li>
</ul></li>
<li>Stability and being boring after 1.0.0 is reached</li>
</ul>
<h2 id="non-goals">Non goals</h2>
<p><a name="non-goals"></a></p>
<ul>
<li>Compiling of used library C code at any point
<ul>
<li>That is no stubs, no C code generated by the library and so
on</li>
<li>The pffi library itself may require compilation on
installation</li>
</ul></li>
</ul>
<h2 id="status">Status</h2>
<p><a name="status"></a></p>
<p>In alpha.</p>
<h3 id="current-caveats">Current caveats</h3>
<p><a name="current-caveats"></a></p>
<ul>
<li>No way to pass structs by value</li>
<li>Most implementations are missing callback support</li>
<li>Always pass arguments to pffi functions/macros as (1 2 3)
and not (list 1 2 3)</li>
<li>Always pass pffi-define-callback procedure as lambda in
place</li>
<li>No support for variadic function arguments
<ul>
<li>Can be partially worked around by defining multiple versions
of same function with different number of arguments</li>
</ul></li>
</ul>
<h2 id="roadmap">Roadmap</h2>
<p>For roadmap to 1.0.0 see <a
href="https://todo.sr.ht/~retropikzel/r7rs-pffi?search=status%3Aopen%20label%3A%221.0.0%22">issues</a></p>
<h2 id="feature-mplementation-table">Feature mplementation
table</h2>
<p><a name="feature-implementation-table"></a></p>
<h2 id="primitives">Primitives</h2>
<p><a name="feature-implementation-table-primitives"></a></p>
<table>
<colgroup>
<col style="width: 9%" />
<col style="width: 9%" />
<col style="width: 14%" />
<col style="width: 10%" />
<col style="width: 13%" />
<col style="width: 12%" />
<col style="width: 14%" />
<col style="width: 15%" />
</colgroup>
<thead>
<tr class="header">
<th></th>
<th style="text-align: center;">c-size-of</th>
<th style="text-align: center;">define-c-library</th>
<th style="text-align: center;">c-bytevector?</th>
<th style="text-align: center;">pffi-pointer-set!</th>
<th style="text-align: center;">pffi-pointer-get</th>
<th style="text-align: center;">define-c-procedure</th>
<th style="text-align: center;">pffi-define-callback</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Chibi</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;"></td>
</tr>
<tr class="even">
<td>Chicken</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
</tr>
<tr class="odd">
<td>Cyclone</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;"></td>
</tr>
<tr class="even">
<td>Gambit</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
</tr>
<tr class="odd">
<td>Gauche</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;"></td>
</tr>
<tr class="even">
<td>Gerbil</td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
</tr>
<tr class="odd">
<td>Guile</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
</tr>
<tr class="even">
<td>Kawa</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
</tr>
<tr class="odd">
<td>Larceny</td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
</tr>
<tr class="even">
<td>Mosh</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
</tr>
<tr class="odd">
<td>Racket</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
</tr>
<tr class="even">
<td>Saggittarius</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
</tr>
<tr class="odd">
<td>Skint</td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
</tr>
<tr class="even">
<td>Stklos</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
</tr>
<tr class="odd">
<td>tr7</td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
</tr>
<tr class="even">
<td>Ypsilon</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
</tr>
</tbody>
</table>
<h2 id="built-upon">Built upon</h2>
<p><a name="feature-implementation-table-built-upon"></a></p>
<p>These features are built upon the primitives and if
primitives are implemented and work, they should work too.</p>
<ul>
<li>make-c-bytevector</li>
<li>make-c-null</li>
<li>c-null?</li>
<li>pffi-pointer-address</li>
<li>c-free</li>
<li>pffi-pointer-&gt;string</li>
<li>pffi-string-&gt;pointer</li>
<li>pffi-struct-make</li>
<li>pffi-struct-pointer</li>
<li>pffi-struct-offset-get</li>
<li>pffi-struct-get</li>
<li>pffi-struct-set!</li>
<li>pffi-array-allocate</li>
<li>pffi-array?</li>
<li>pffi-pointer-&gt;array</li>
<li>pffi-array-get</li>
<li>pffi-array-set!</li>
<li>pffi-list-&gt;array</li>
<li>pffi-array-&gt;list</li>
</ul>
<h3 id="not-started">Not started</h3>
<p><a name="not-started"></a></p>
<ul>
<li><a href="https://lips.js.org/">LIPS</a>
<ul>
<li>Will work on nodejs by using some C FFI library from
npm</li>
<li>Javascript side needs design</li>
</ul></li>
<li><a href="https://www.biwascheme.org/">Biwascheme</a>
<ul>
<li>Will work on nodejs by using some C FFI library from
npm</li>
<li>Javascript side needs design</li>
</ul></li>
<li><a
href="https://www.gnu.org/software/mit-scheme/">MIT-Scheme</a>
<ul>
<li>Need to study the implementation more</li>
</ul></li>
<li><a
href="https://gitlab.com/mbabich/airship-scheme">Airship</a>
<ul>
<li>Need to study the implementation more</li>
</ul></li>
<li><a href="https://gambitscheme.org/">Other gambit targets</a>
<ul>
<li>Gambit compiles to different targets other than C too, for
example Javascript. It would be cool and interesting to see if
this FFI could also support some of those</li>
<li>When LIPS and Biwascheme Javascript side is done then Gambit
should be done too</li>
</ul></li>
<li><a
href="https://codeberg.org/prescheme/s48-r7rs">s48-r7rs</a>
<ul>
<li>Need to study the implementation more</li>
</ul></li>
<li><a
href="https://codeberg.org/prescheme/prescheme">prescheme</a>
<ul>
<li>Need to study the implementation more</li>
</ul></li>
</ul>
<h3 id="other">Other</h3>
<p><a name="other"></a></p>
<ul>
<li><a
href="https://scheme.fail://ccrma.stanford.edu/software/snd/snd/s7.html">s7</a>
<ul>
<li>Propably does not need FFI as it is embeddable only</li>
</ul></li>
<li><a href="https://scheme.fail/">Loko</a>
<ul>
<li>Desires no C interop, I can respect that</li>
</ul></li>
</ul>
<h2 id="documentation">Documentation</h2>
<p><a name="documentation"></a></p>
<h3 id="dependencies">Dependencies</h3>
<p><a name="dependencies"></a></p>
<p>Some implementations have extra dependencies/requirements
beyond just the library.</p>
<h4 id="chibi">Chibi</h4>
<p><a name="dependencies-chibi"></a></p>
<p>Building depends on libffi.</p>
<p>Debian/Ubuntu/Mint install with:</p>
<pre><code>apt install libffi-dev</code></pre>
<h4 id="chicken">Chicken</h4>
<p><a name="dependencies-chicken"></a></p>
<p>Chicken needs r7rs egg installed. Install it with:</p>
<pre><code>chicken-install r7rs</code></pre>
<h4 id="gauche">Gauche</h4>
<p><a name="dependencies-gauche"></a></p>
<p>Building depends on libffi.</p>
<p>Debian/Ubuntu/Mint install with:</p>
<pre><code>apt install libffi-dev</code></pre>
<h4 id="racket">Racket</h4>
<p><a name="dependencies-racket"></a></p>
<p>Needs <a
href="https://github.com/lexi-lambda/racket-r7rs">racket-r7rs</a>,
install with:</p>
<pre><code>raco pkg install --auto r7rs</code></pre>
<h4 id="kawa">Kawa</h4>
<p><a name="dependencies-kawa"></a></p>
<p>Kawa Needs at least Java version 22 these flags before any
other arguments:</p>
<ul>
<li>-Jadd-exports=java.base/jdk.internal.foreign.abi=ALL-UNNAMED</li>
<li>-Jadd-exports=java.base/jdk.internal.foreign.layout=ALL-UNNAMED</li>
<li>-Jadd-exports=java.base/jdk.internal.foreign=ALL-UNNAMED</li>
<li>-Jenable-native-access=ALL-UNNAMED</li>
</ul>
<p>If you are running kawa.jar with plain java then give same
arguments to java without the -J prefix.</p>
<h3 id="installation">Installation</h3>
<p><a name="installation"></a></p>
<p>Since the project is under active development is best to
clone it from git,</p>
<h3 id="project-local">Project local</h3>
<p><a name="installation-project-local"></a></p>
<h4 id="linux">Linux</h4>
<p><a name="installation-project-local-linux"></a> Assuming you
have a project and your libraries live in directory called snow
in it:</p>
<pre><code>git clone https://git.sr.ht/~retropikzel/r7rs-pffi
mkdir -p snow
cp -r r7rs-pffi/retropikzel snow/
cd snow/retropikzel/pffi
make &lt;SCHEME&gt;</code></pre>
<h4 id="windows">Windows</h4>
<p><a name="installation-project-local-windows"></a></p>
<p>There is no build scripts yet for Windows, that said many
implementations work without compiling anything. If you run this
and it says “There is notching to build for SCHEME” then you
should be good to go.</p>
<h3 id="system-global">System global</h3>
<p><a name="installation-system-global"></a></p>
<p>Still work in progress.</p>
<h2 id="reference">Reference</h2>
<p><a name="reference"></a></p>
<h3 id="types">Types</h3>
<p><a name="types"></a></p>
<p>Types are given as symbols, for example int8 or
pointer.</p>
<ul>
<li>int8</li>
<li>uint8</li>
<li>int16</li>
<li>uint16</li>
<li>int32</li>
<li>uint32</li>
<li>int64</li>
<li>uint64</li>
<li>char</li>
<li>unsigned-char</li>
<li>short</li>
<li>unsigned-short</li>
<li>int</li>
<li>unsigned-int</li>
<li>long</li>
<li>unsigned-long</li>
<li>float</li>
<li>double</li>
<li>pointer</li>
<li>callback
<ul>
<li>Callback function</li>
</ul></li>
</ul>
<h3 id="types-1">Types</h3>
<p><a name="types"></a></p>
<h3 id="environment-variables">Environment variables</h3>
<p><a name="environment-variables"></a></p>
<p>Setting environment variables like this on Windows works for
this library:</p>
<pre><code>set &quot;PFFI_LOAD_PATH=C:\Program Files (x86)/foo/bar&quot;</code></pre>
<h4 id="pffi_load_path">PFFI_LOAD_PATH</h4>
<p><a name="environment-variables-pffi-load-path"></a></p>
<p>To add more paths to where pffi looks for libraries set
PFFI_LOAD_PATH to paths separated by ; on windows, and : on
other operating systems.</p>
<h3 id="procedures-and-macros">Procedures and macros</h3>
<p><a name="procedures-and-macros"></a></p>
<p>Some of these are procedures and some macros, it might also
change implementation to implementation.</p>
<h4 id="pffi-init">pffi-init</h4>
<p><a name="pffi-init"></a></p>
<p><strong>pffi-init</strong></p>
<p>Always call this first, on most implementation it does
nothing but some implementations might need initialisation
run.</p>
<h4 id="c-size-of">c-size-of</h4>
<p><a name="c-size-of"></a></p>
<p><strong>c-size-of</strong> object -&gt; number</p>
<p>Returns the size of the pffi-struct, pffi-enum or
pffi-type.</p>
<h4 id="pffi-align-of">pffi-align-of</h4>
<p><a name="pffi-align-of"></a></p>
<p><strong>pffi-align-of</strong> type -&gt; number</p>
<p>Returns the align of the type.</p>
<h4 id="define-c-library">define-c-library</h4>
<p><a name="define-c-library"></a></p>
<p><strong>define-c-library</strong> headers shared-object-name
[options] -&gt; object</p>
<p>Load given shared object automatically searching many
predefined paths.</p>
<p>Takes as argument a list of C headers, these are for the
compiler ones. And an shared-object name, used by the dynamic
FFIs. The name of the shared object should not contain suffix
like .so or .dll. Nor should it contain any prefix like
“lib”.</p>
<p>Additional options argument can be provided, theys should be
a pair with a keyword. The options are:</p>
<ul>
<li>additional-versions
<ul>
<li>Search for additional versions of shared object, given
shared object “c” and additional versions “6” “7” on linux the
files “libc”, “libc.6”, “libc.7” are searched for.</li>
<li>Can be either numbers or strings</li>
</ul></li>
<li>additional-paths
<ul>
<li>Give additional paths to search shared objects for</li>
</ul></li>
</ul>
<p>Example:</p>
<pre><code>(cond-expand
(windows (define-c-library libc-stdlib
&#39;(&quot;stdlib.h&quot;)
&quot;ucrtbase&quot;
&#39;((additional-versions (&quot;0&quot; &quot;6&quot;))
(additiona-paths (&quot;.&quot;)))))
(else (define-c-library libc-stdlib
(list &quot;stdlib.h&quot;)
&quot;c&quot;
&#39;((additional-versions (&quot;0&quot; &quot;6&quot;))
(additiona-paths (&quot;.&quot;))))))</code></pre>
<h4 id="notes">Notes</h4>
<ul>
<li>Do not cond-expand inside the arguments, that might lead to
problems on some implementations.</li>
<li>Do not store options in variables, that might lead to
problems on some implementations.</li>
<li>Do pass the headers using quote
<ul>
<li>As (… and not (list…</li>
</ul></li>
<li>Do pass the options using quote
<ul>
<li>As (… and not (list…</li>
</ul></li>
</ul>
<h4 id="make-c-null">make-c-null</h4>
<p><a name="make-c-null"></a></p>
<p><strong>make-c-null</strong> -&gt; pointer</p>
<p>Returns a new NULL pointer.</p>
<h4 id="c-null">c-null?</h4>
<p><a name="is-c-null"></a></p>
<p><strong>c-null?</strong> pointer -&gt; boolean</p>
<p>Returns #t if given pointer is null pointer, #f
otherwise.</p>
<h4 id="make-c-bytevector">make-c-bytevector</h4>
<p><a name="make-c-bytevector "></a></p>
<p><strong>make-c-bytevector</strong> size -&gt; pointer</p>
<p>Returns newly allocated pointer of given size.</p>
<h4 id="pffi-pointer-address">pffi-pointer-address</h4>
<p><a name="pffi-pointer-address"></a></p>
<p><strong>pffi-pointer-address</strong> pointer -&gt;
pointer</p>
<p>Returns the address of given pointer inside a pointer. This
is used when passing pointers to pointers to foreign procedures.
This is similar to the cs &amp;. One <strong>important
difference</strong> is that after you have passed a pointer to
the procedure you must get value from it back to the pointer
which address you are passing. Example:</p>
<pre><code>(define input-pointer (make-c-bytevector &lt;needed size&gt;))
(define input-pointer-address (pffi-pointer-address input-pointer))
(&lt;foreign-procedure-that takes &amp;pointer as argument&gt; input-pointer-address)
(set! input-pointer (pffi-pointer-get input-pointer-address &#39;pointer 0))</code></pre>
<h4 id="c-bytevector">c-bytevector?</h4>
<p><a name="pffi-pointer"></a></p>
<p><strong>c-bytevector?</strong> object -&gt; boolean</p>
<p>Returns #t if given object is pointer, #f otherwise.</p>
<h4 id="c-free">c-free</h4>
<p><a name="c-free"></a></p>
<p><strong>c-free</strong> pointer</p>
<p>Frees given pointer.</p>
<h4 id="pffi-pointer-set">pffi-pointer-set!</h4>
<p><a name="pffi-pointer-set!"></a></p>
<p><strong>pffi-pointer-set!</strong> pointer type offset
value</p>
<p>Sets the value on a pointer on given offset. For example:</p>
<pre><code>(define p (make-c-bytevector 128))
(pffi-pointer-set! p &#39;int 64 100)</code></pre>
<p>Would set the offset of 64, on pointer p to value 100.</p>
<h4 id="pffi-pointer-get">pffi-pointer-get</h4>
<p><a name="pffi-pointer-get"></a></p>
<p><strong>pffi-pointer-get</strong> pointer type offset -&gt;
object</p>
<p>Gets the value from a pointer on given offset. For
example:</p>
<pre><code>(define p (make-c-bytevector 128))
(pffi-pointer-set! p &#39;int 64 100)
(pffi-pointer-get p &#39;int 64)
&gt; 100</code></pre>
<h4 id="string-c-bytevector">string-&gt;c-bytevector</h4>
<p><a name="string-into-c-bytevector"></a></p>
<p><strong>string-&gt;c-bytevector</strong> string -&gt;
pointer</p>
<p>Makes pointer out of a given string.</p>
<h4 id="c-bytevector-string">c-bytevector-&gt;string</h4>
<p><a name="c-bytevector-into-string"></a></p>
<p><strong>c-bytevector-&gt;sring</strong> pointer -&gt;
string</p>
<p>Makes string out of a given pointer.</p>
<h4 id="pffi-struct-make">pffi-struct-make</h4>
<p><a name="pffi-struct-make"></a></p>
<p><strong>pffi-struct-make</strong> c-type members . pointer
-&gt; pffi-struct</p>
<p>Creates a new pffi-struct and allocates pointer for it. The
members argument is a list of member names and types. For
example:</p>
<pre><code>(define color (pffi-struct-make &#39;color &#39;((int8 . r) (int8 . g) (int8 . b) (int8 .a ))))
(define test (pffi-struct-make &quot;struct test&quot; &#39;((int8 . r) (int8 . g) (int8 . b) (int8 .a ))))</code></pre>
<p>C-type argument can be symbol or a string.</p>
<h4 id="pffi-struct-pointer">pffi-struct-pointer</h4>
<p><a name="pffi-struct-pointer"></a></p>
<p><strong>pffi-struct-pointer</strong> pffi-struct -&gt;
pointer</p>
<p>Returns the pointer that holds the struct content. You need
to use this when passing a struct as a pointer to foreign
functions.</p>
<pre><code>(define s (pffi-struct-make &#39;test &#39;((int . r) (int . g) (int . b))))
(pffi-struct-pointer s)</code></pre>
<h4 id="pffi-struct-offset-get">pffi-struct-offset-get</h4>
<p><a name="pffi-struct-offset-get"></a></p>
<p><strong>pffi-struct-offset-get</strong> member-name -&gt;
number</p>
<p>Returns the offset of a struct member with given name.</p>
<h4 id="pffi-struct-get">pffi-struct-get</h4>
<p><a name="pffi-struct-get"></a></p>
<p><strong>pffi-struct-get</strong> pffi-struct member-name
-&gt; object</p>
<p>Returns the value of the givens struct member.</p>
<h4 id="pffi-struct-set">pffi-struct-set!</h4>
<p><a name="pffi-struct-set!"></a></p>
<p><strong>pffi-struct-set!</strong> pffi-struct member-name
value</p>
<p>Sets the value of the givens struct member. It is up to you
to make sure that the type of value is correct.</p>
<h4 id="pffi-array-allocate">pffi-array-allocate</h4>
<p><a name="pffi-array-allocate"></a></p>
<p><strong>pffi-array-allocate</strong> type size</p>
<p>Allocates pointer array of given type and size.</p>
<h4 id="pffi-array-pointer">pffi-array-pointer</h4>
<p><a name="pffi-array-pointer"></a></p>
<p><strong>pffi-array-pointer</strong> array</p>
<p>Returns the pointer of the array.</p>
<h4 id="pffi-array">pffi-array?</h4>
<p><a name="pffi-array"></a></p>
<p><strong>pffi-array?</strong> object</p>
<p>Returns #t of given object is array, #f otherwise.</p>
<h4 id="pffi-pointer-array">pffi-pointer-&gt;array</h4>
<p><a name="pffi-pointer->array"></a></p>
<p><strong>pffi-pointer-&gt;array</strong> pointer type size</p>
<p>Converts given pointer to an array of giben type and
size.</p>
<h4 id="pffi-array-get">pffi-array-get</h4>
<p><a name="pffi-array-get"></a></p>
<p><strong>pffi-array-get</strong> array index</p>
<p>Returns the value of given index from given array.</p>
<h4 id="pffi-array-set">pffi-array-set!</h4>
<p><a name="pffi-array-set!"></a></p>
<p><strong>pffi-array-set!</strong> array index value</p>
<p>Sets the given value of given index in given array.</p>
<h4 id="pffi-list-array">pffi-list-&gt;array</h4>
<p><a name="pffi-list->array"></a></p>
<p><strong>pffi-list-&gt;array</strong> type list</p>
<p>Converts given list into C array of given type.</p>
<h4 id="pffi-array-list">pffi-array-&gt;list</h4>
<p><a name="pffi-array->list"></a></p>
<p><strong>pffi-array-&gt;list</strong> type list length</p>
<p>Converts given C array into list of given type and
length.</p>
<h4 id="define-c-procedure">define-c-procedure</h4>
<p><a name="define-c-procedure"></a></p>
<p><strong>define-c-procedure</strong> scheme-name shared-object
c-name return-type argument-types</p>
<p>Defines a new foreign function to be used from Scheme code.
For example:</p>
<pre><code>(cond-expand
(windows (define-c-library libc-stdlib &#39;(&quot;stdlib.h&quot;) &quot;ucrtbase&quot; &#39;(&quot;&quot;)))
(else (define-c-library libc-stdlib &#39;(&quot;stdlib.h&quot;) &quot;c&quot; &#39;(&quot;&quot; &quot;6&quot;))))
(define-c-procedure c-puts libc-stdlib &#39;puts &#39;int &#39;(pointer))
(c-puts &quot;Message brought to you by FFI!&quot;)</code></pre>
<h4 id="pffi-define-callback">pffi-define-callback</h4>
<p><a name="pffi-define-callback"></a></p>
<p><strong>pffi-define-callback</strong> scheme-name return-type
argument-types procedure</p>
<p>Defines a new Sceme function to be used as callback to C
code. For example:</p>
<pre><code>; Load the shared library
(cond-expand
(windows (define-c-library libc-stdlib &#39;(&quot;stdlib.h&quot;) &quot;ucrtbase&quot; &#39;()))
(else (define-c-library &#39;(&quot;stdlib.h&quot;) &quot;c&quot; &#39;(&quot;&quot; &quot;6&quot;))))
; Define C function that takes a callback
(define-c-procedure qsort libc-stdlib &#39;qsort &#39;void &#39;(pointer int int callback))
; Define our callback
(pffi-define-callback compare
&#39;int
&#39;(pointer pointer)
(lambda (pointer-a pointer-b)
(let ((a (pffi-pointer-get pointer-a &#39;int 0))
(b (pffi-pointer-get pointer-b &#39;int 0)))
(cond ((&gt; a b) 1)
((= a b) 0)
((&lt; a b) -1)))))
; Create new array of ints to be sorted
(define array (make-c-bytevector (* (c-size-of &#39;int) 3)))
(pffi-pointer-set! array &#39;int (* (c-size-of &#39;int) 0) 3)
(pffi-pointer-set! array &#39;int (* (c-size-of &#39;int) 1) 2)
(pffi-pointer-set! array &#39;int (* (c-size-of &#39;int) 2) 1)
(display array)
(newline)
;&gt; (3 2 1)
; Sort the array
(qsort array 3 (c-size-of &#39;int) compare)
(display array)
(newline)
;&gt; (1 2 3)</code></pre>
</main>
</body>
</html>