Updated documentation

This commit is contained in:
retropikzel 2025-05-03 05:47:20 +03:00
parent 009a3a5d64
commit 41c6097470
6 changed files with 371 additions and 799 deletions

View File

@ -11,7 +11,7 @@ being portable by conforming to some specification.
The new readme is a work in progress.
## Implementation table
## Implementation support tables
### Primitives 1
@ -58,16 +58,59 @@ The new readme is a work in progress.
| Stklos | X | X | |
| Ypsilon | X | X | |
### Installation
Either download the latest release from
[releases page](https://git.sr.ht/~retropikzel/foreign-c/refs) or git clone
, preferably with a tag, and copy the "foreign" directory to your library
directory.
As an example assuming you have a project and your libraries live in directory
called snow in it:
git clone https://git.sr.ht/~retropikzel/foreign-c --branch LATEST_VERSION
mkdir -p snow
cp -r foreign-c/foreign snow/
make -C snow/foreign/c <SCHEME_IMPLEMENTATION_NAME>
With most implementations the make command does not compile anything. When that
is the case it will say "Nothing to build on SCHEME\_IMPLEMENTATION\_NAME."
## Documentation
### Types
Types are given as symbols, for example 'int8 or 'pointer.
- int8
- uint8
- int16
- uint16
- int32
- uint32
- int64
- uint64
- char
- unsigned-char
- short
- unsigned-short
- int
- unsigned-int
- long
- unsigned-long
- float
- double
- pointer
- callback
- Callback function
### Primitives
(**c-type-size** _type_)
Returns the size of given C type.
(define-c-library)
(**define-c-library** _scheme-name_ _headers_ _object-name_ _options_)
define-c-procedure
define-c-callback
c-bytevector?

1
VERSION Normal file
View File

@ -0,0 +1 @@
0.10.0

View File

@ -1,797 +0,0 @@
<!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>

Binary file not shown.

View File

@ -0,0 +1,325 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>(foreign c) a portable foreign function interface for
R7RS - 0.10.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="foreign-c">(foreign c)</h1>
<p>(foreign c) is a C foreign function interface (FFI) library
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>The new readme is a work in progress.</p>
<h2 id="implementation-table">Implementation table</h2>
<h3 id="primitives-1">Primitives 1</h3>
<table>
<colgroup>
<col style="width: 13%" />
<col style="width: 10%" />
<col style="width: 16%" />
<col style="width: 15%" />
<col style="width: 16%" />
<col style="width: 11%" />
<col style="width: 16%" />
</colgroup>
<thead>
<tr class="header">
<th></th>
<th style="text-align: center;">c-size-of</th>
<th style="text-align: center;">c-bytevector-u8-set!</th>
<th style="text-align: center;">c-bytevector-u8-ref</th>
<th style="text-align: center;">define-c-library</th>
<th style="text-align: center;">c-bytevector?</th>
<th style="text-align: center;">define-c-procedure</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>Chibi</strong></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><strong>Chicken</strong></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><strong>Gauche</strong></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><strong>Guile</strong></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><strong>Kawa</strong></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><strong>Mosh</strong></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><strong>Racket</strong></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><strong>Saggittarius</strong></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><strong>Stklos</strong></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><strong>Ypsilon</strong></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>
<h3 id="primitives-2">Primitives 2</h3>
<table>
<thead>
<tr class="header">
<th></th>
<th style="text-align: center;">define-c-callback</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Chibi</td>
<td style="text-align: center;"></td>
</tr>
<tr class="even">
<td><strong>Chicken</strong></td>
<td style="text-align: center;">X</td>
</tr>
<tr class="odd">
<td>Gauche</td>
<td style="text-align: center;"></td>
</tr>
<tr class="even">
<td><strong>Guile</strong></td>
<td style="text-align: center;">X</td>
</tr>
<tr class="odd">
<td>Kawa</td>
<td style="text-align: center;"></td>
</tr>
<tr class="even">
<td><strong>Mosh</strong></td>
<td style="text-align: center;">X</td>
</tr>
<tr class="odd">
<td><strong>Racket</strong></td>
<td style="text-align: center;">X</td>
</tr>
<tr class="even">
<td><strong>Saggittarius</strong></td>
<td style="text-align: center;">X</td>
</tr>
<tr class="odd">
<td>Stklos</td>
<td style="text-align: center;"></td>
</tr>
<tr class="even">
<td><strong>Ypsilon</strong></td>
<td style="text-align: center;">X</td>
</tr>
</tbody>
</table>
<h3 id="test-files-pass">Test files pass</h3>
<table>
<thead>
<tr class="header">
<th></th>
<th style="text-align: center;">primitives.scm</th>
<th style="text-align: center;">addressof.scm</th>
<th style="text-align: right;">callback.scm</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: right;"></td>
</tr>
<tr class="even">
<td><strong>Chicken</strong></td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: right;">X</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: right;"></td>
</tr>
<tr class="even">
<td><strong>Guile</strong></td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: right;">X</td>
</tr>
<tr class="odd">
<td>Kawa</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: right;"></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: right;"></td>
</tr>
<tr class="odd">
<td>Racket</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;"></td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td><strong>Saggittarius</strong></td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: right;">X</td>
</tr>
<tr class="odd">
<td>Stklos</td>
<td style="text-align: center;">X</td>
<td style="text-align: center;">X</td>
<td style="text-align: right;"></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: right;"></td>
</tr>
</tbody>
</table>
<h2 id="documentation">Documentation</h2>
<h3 id="types">Types</h3>
<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="primitives">Primitives</h3>
<p>(<strong>c-type-size</strong> <em>type</em>)</p>
<p>Returns the size of given C type.</p>
<p>(<strong>define-c-library</strong> <em>scheme-name</em>
<em>headers</em> <em>object-name</em> <em>options</em>)
define-c-procedure define-c-callback c-bytevector?
c-bytevector-u8-set! c-bytevector-u8-ref
c-bytevector-pointer-set! c-bytevector-pointer-ref</p>
<h3 id="c-bytevector">c-bytevector</h3>
<p>make-c-bytevector make-c-null c-null? c-free
native-endianness c-bytevector-s8-set! c-bytevector-s8-ref
c-bytevector-s16-set! c-bytevector-s16-ref
c-bytevector-s16-native-set! c-bytevector-s16-native-ref
c-bytevector-u16-set! c-bytevector-u16-ref
c-bytevector-u16-native-set! c-bytevector-u16-native-ref
c-bytevector-s32-set! c-bytevector-s32-ref
c-bytevector-s32-native-set! c-bytevector-s32-native-ref
c-bytevector-u32-set! c-bytevector-u32-ref
c-bytevector-u32-native-set! c-bytevector-u32-native-ref
c-bytevector-s64-set! c-bytevector-s64-ref
c-bytevector-s64-native-set! c-bytevector-s64-native-ref
c-bytevector-u64-set! c-bytevector-u64-ref
c-bytevector-u64-native-set! c-bytevector-u64-native-ref
c-bytevector-sint-set! c-bytevector-sint-ref
c-bytevector-uint-set! c-bytevector-uint-ref
c-bytevector-ieee-single-set!
c-bytevector-ieee-single-native-set!
c-bytevector-ieee-single-ref c-bytevector-ieee-single-native-ref
c-bytevector-ieee-double-set!
c-bytevector-ieee-double-native-set!
c-bytevector-ieee-double-ref c-bytevector-ieee-double-native-ref
bytevector-&gt;c-bytevector c-bytevector-&gt;bytevector
call-with-address-of</p>
<p>string-&gt;c-utf8 c-utf8-&gt;string</p>
</body>
</html>

BIN
documentation/foreign-c.pdf Normal file

Binary file not shown.