655 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Markdown
		
	
	
	
			
		
		
	
	
			655 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Markdown
		
	
	
	
---
 | 
						|
title: Portable Foreign Function Interface for R7RS Documentation
 | 
						|
version: 0.6.0
 | 
						|
---
 | 
						|
 | 
						|
# Portable Foreign Function Interface for R7RS
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
[Project](https://todo.sr.ht/~retropikzel/r7rs-pffi)
 | 
						|
 | 
						|
[Issue trackers](https://sr.ht/~retropikzel/r7rs-pffi/trackers)
 | 
						|
 | 
						|
[Maling lists](https://sr.ht/~retropikzel/r7rs-pffi/lists)
 | 
						|
 | 
						|
[Jenkins](https://jenkins.scheme.org/job/r7rs_pffi/job/r7rs-pffi/)
 | 
						|
 | 
						|
## Table of contents
 | 
						|
 | 
						|
<nav>
 | 
						|
 | 
						|
- [Goals](#goals)
 | 
						|
- [Non Goals](#non-goals)
 | 
						|
- [Status](#status)
 | 
						|
    - [Current caveats](#current-caveats)
 | 
						|
- [Roadmap](#roadmap)
 | 
						|
- [Feature implementation table](#feature-implementation-table)
 | 
						|
    - [Primitives](#feature-implementation-table-primitives)
 | 
						|
    - [Built upon](#feature-implementation-table-built-upon)
 | 
						|
- [Documentation](#documentation)
 | 
						|
    - [Dependencies](#dependencies)
 | 
						|
        - [Chibi](#dependencies-chibi)
 | 
						|
        - [Chicken](#dependencies-chicken)
 | 
						|
        - [Gauche](#dependencies-gauche)
 | 
						|
        - [Racket](#dependencies-racket)
 | 
						|
        - [Kawa](#dependencies-kawa)
 | 
						|
    - [Installation](#installation)
 | 
						|
        - [Project local](#installation-project-local)
 | 
						|
            - [Linux](#installation-project-local-linux)
 | 
						|
            - [Windows](#installation-project-local-windows)
 | 
						|
        - [System global](#installation-system-global)
 | 
						|
- [Reference](#reference)
 | 
						|
    - [Types](#types)
 | 
						|
    - [Environment variables](#environment-variables)
 | 
						|
        - [PFFI\_LOAD\_PATH](#environment-variables-pffi-load-path)
 | 
						|
    - [Procedures and macros](#procedures-and-macros)
 | 
						|
        - [pffi-init](#pffi-init)
 | 
						|
        - [c-size-of](#c-size-of)
 | 
						|
        - [pffi-align-of](#pffi-align-of)
 | 
						|
        - [define-c-library](#define-c-library)
 | 
						|
        - [make-c-null](#make-c-null)
 | 
						|
        - [c-null?](#is-c-null)
 | 
						|
        - [make-c-bytevector ](#make-c-bytevector )
 | 
						|
        - [pffi-pointer-address](#pffi-pointer-address)
 | 
						|
        - [c-bytevector?](#is-c-bytevector)
 | 
						|
        - [c-free](#c-free)
 | 
						|
        - [pffi-pointer-set!](#pffi-pointer-set!)
 | 
						|
        - [pffi-pointer-get](#pffi-pointer-get)
 | 
						|
        - [utf8->c-bytevector](#utf8-into-c-bytevector)
 | 
						|
        - [c-bytevector->sring](#c-bytevector-into-string)
 | 
						|
        - [pffi-struct-make](#pffi-struct-make)
 | 
						|
        - [pffi-struct-pointer](#pffi-struct-pointer)
 | 
						|
        - [pffi-struct-offset-get](#pffi-struct-offset-get)
 | 
						|
        - [pffi-struct-get](#pffi-struct-get)
 | 
						|
        - [pffi-struct-set!](#pffi-struct-set!)
 | 
						|
        - [pffi-array-allocate](#pffi-array-allocate)
 | 
						|
        - [pffi-array-pointer](#pffi-array-pointer)
 | 
						|
        - [pffi-array?](#pffi-array)
 | 
						|
        - [pffi-pointer->array](#pffi-pointer->array)
 | 
						|
        - [pffi-array-get](#pffi-array-get)
 | 
						|
        - [pffi-array-set!](#pffi-array-set!)
 | 
						|
        - [pffi-list->array](#pffi-list->array)
 | 
						|
        - [pffi-array->list](#pffi-array->list)
 | 
						|
        - [define-c-procedure](#define-c-procedure)
 | 
						|
        - [pffi-define-callback](#pffi-define-callback)
 | 
						|
 | 
						|
</nav>
 | 
						|
 | 
						|
<main>
 | 
						|
 | 
						|
## Goals
 | 
						|
<a name="goals"></a>
 | 
						|
 | 
						|
- Support only R7RS implementations
 | 
						|
- Same interface on all implementations
 | 
						|
  - Some things that are procedures on one implementation are macros on other,
 | 
						|
  but they must behave the same
 | 
						|
- Stability and being boring after 1.0.0 is reached
 | 
						|
 | 
						|
## Non goals
 | 
						|
<a name="non-goals"></a>
 | 
						|
 | 
						|
- Compiling of used library C code at any point
 | 
						|
    - That is no stubs, no C code generated by the library and so on
 | 
						|
    - The pffi library itself may require compilation on installation
 | 
						|
 | 
						|
## Status
 | 
						|
<a name="status"></a>
 | 
						|
 | 
						|
In alpha.
 | 
						|
 | 
						|
### Current caveats
 | 
						|
<a name="current-caveats"></a>
 | 
						|
 | 
						|
- No way to pass structs by value
 | 
						|
- Most implementations are missing callback support
 | 
						|
- Always pass arguments to pffi functions/macros as '(1 2 3) and not (list 1 2 3)
 | 
						|
- Always pass pffi-define-callback procedure as lambda in place
 | 
						|
- No support for variadic function arguments
 | 
						|
    - Can be partially worked around by defining multiple versions of same
 | 
						|
    function with different number of arguments
 | 
						|
 | 
						|
## Roadmap
 | 
						|
 | 
						|
For roadmap to 1.0.0 see [issues](https://todo.sr.ht/~retropikzel/r7rs-pffi?search=status%3Aopen%20label%3A%221.0.0%22)
 | 
						|
 | 
						|
## Feature mplementation table
 | 
						|
<a name="feature-implementation-table"></a>
 | 
						|
 | 
						|
## Primitives
 | 
						|
<a name="feature-implementation-table-primitives"></a>
 | 
						|
 | 
						|
|              | c-size-of    | define-c-library    | c-bytevector? | pffi-pointer-set! | pffi-pointer-get | define-c-procedure | pffi-define-callback |
 | 
						|
|--------------|:------------:|:-------------------:|:-------------:|:-----------------:|:----------------:|:-------------------:|:--------------------:|
 | 
						|
| Chibi        | X            | X                   | X             | X                 | X                | X                   |                      |
 | 
						|
| Chicken      | X            | X                   | X             | X                 | X                | X                   | X                    |
 | 
						|
| Cyclone      | X            | X                   | X             | X                 | X                | X                   |                      |
 | 
						|
| Gambit       | X            |                     |               |                   |                  |                     |                      |
 | 
						|
| Gauche       | X            | X                   | X             | X                 | X                | X                   |                      |
 | 
						|
| Gerbil       |              |                     |               |                   |                  |                     |                      |
 | 
						|
| Guile        | X            | X                   | X             | X                 | X                | X                   | X                    |
 | 
						|
| Kawa         | X            | X                   | X             | X                 | X                | X                   | X                    |
 | 
						|
| Larceny      |              |                     |               |                   |                  |                     |                      |
 | 
						|
| Mosh         | X            | X                   | X             | X                 | X                | X                   | X                    |
 | 
						|
| Racket       | X            | X                   | X             | X                 | X                | X                   | X                    |
 | 
						|
| Saggittarius | X            | X                   | X             | X                 | X                | X                   | X                    |
 | 
						|
| Skint        |              |                     |               |                   |                  |                     |                      |
 | 
						|
| Stklos       | X            | X                   | X             |                   |                  |                     |                      |
 | 
						|
| tr7          |              |                     |               |                   |                  |                     |                      |
 | 
						|
| Ypsilon      | X            | X                   | X             | X                 | X                | X                   | X                    |
 | 
						|
 | 
						|
## Built upon
 | 
						|
<a name="feature-implementation-table-built-upon"></a>
 | 
						|
 | 
						|
These features are built upon the primitives and if primitives are implemented
 | 
						|
and work, they should work too.
 | 
						|
 | 
						|
- make-c-bytevector
 | 
						|
- make-c-null
 | 
						|
- c-null?
 | 
						|
- pffi-pointer-address
 | 
						|
- c-free
 | 
						|
- pffi-pointer-\>string
 | 
						|
- pffi-string-\>pointer
 | 
						|
- pffi-struct-make
 | 
						|
- pffi-struct-pointer
 | 
						|
- pffi-struct-offset-get
 | 
						|
- pffi-struct-get
 | 
						|
- pffi-struct-set!
 | 
						|
- pffi-array-allocate
 | 
						|
- pffi-array?
 | 
						|
- pffi-pointer-\>array
 | 
						|
- pffi-array-get
 | 
						|
- pffi-array-set!
 | 
						|
- pffi-list-\>array
 | 
						|
- pffi-array-\>list
 | 
						|
 | 
						|
###  Not started
 | 
						|
<a name="not-started"></a>
 | 
						|
 | 
						|
- [LIPS](https://lips.js.org/)
 | 
						|
    - Will work on nodejs by using some C FFI library from npm
 | 
						|
    - Javascript side needs design
 | 
						|
- [Biwascheme](https://www.biwascheme.org/)
 | 
						|
    - Will work on nodejs by using some C FFI library from npm
 | 
						|
    - Javascript side needs design
 | 
						|
- [MIT-Scheme](https://www.gnu.org/software/mit-scheme/)
 | 
						|
    - Need to study the implementation more
 | 
						|
- [Airship](https://gitlab.com/mbabich/airship-scheme)
 | 
						|
    - Need to study the implementation more
 | 
						|
- [Other gambit targets](https://gambitscheme.org/)
 | 
						|
  - 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
 | 
						|
  - When LIPS and Biwascheme Javascript side is done then Gambit should be done too
 | 
						|
- [s48-r7rs](https://codeberg.org/prescheme/s48-r7rs)
 | 
						|
    - Need to study the implementation more
 | 
						|
- [prescheme](https://codeberg.org/prescheme/prescheme)
 | 
						|
    - Need to study the implementation more
 | 
						|
 | 
						|
### Other
 | 
						|
<a name="other"></a>
 | 
						|
 | 
						|
- [s7](https://scheme.fail://ccrma.stanford.edu/software/snd/snd/s7.html)
 | 
						|
    - Propably does not need FFI as it is embeddable only
 | 
						|
- [Loko](https://scheme.fail/)
 | 
						|
    - Desires no C interop, I can respect that
 | 
						|
 | 
						|
## Documentation
 | 
						|
<a name="documentation"></a>
 | 
						|
 | 
						|
### Dependencies
 | 
						|
<a name="dependencies"></a>
 | 
						|
 | 
						|
Some implementations have extra dependencies/requirements beyond just the
 | 
						|
library.
 | 
						|
 | 
						|
#### Chibi
 | 
						|
<a name="dependencies-chibi"></a>
 | 
						|
 | 
						|
Building depends on libffi.
 | 
						|
 | 
						|
Debian/Ubuntu/Mint install with:
 | 
						|
 | 
						|
    apt install libffi-dev
 | 
						|
 | 
						|
#### Chicken
 | 
						|
<a name="dependencies-chicken"></a>
 | 
						|
 | 
						|
Chicken needs r7rs egg installed. Install it with:
 | 
						|
 | 
						|
    chicken-install r7rs
 | 
						|
 | 
						|
#### Gauche
 | 
						|
<a name="dependencies-gauche"></a>
 | 
						|
 | 
						|
Building depends on libffi.
 | 
						|
 | 
						|
Debian/Ubuntu/Mint install with:
 | 
						|
 | 
						|
    apt install libffi-dev
 | 
						|
 | 
						|
#### Racket
 | 
						|
<a name="dependencies-racket"></a>
 | 
						|
 | 
						|
Needs [racket-r7rs](https://github.com/lexi-lambda/racket-r7rs), install with:
 | 
						|
 | 
						|
    raco pkg install --auto r7rs
 | 
						|
 | 
						|
#### Kawa
 | 
						|
<a name="dependencies-kawa"></a>
 | 
						|
 | 
						|
Kawa Needs at least Java version 22 these flags before any other arguments:
 | 
						|
 | 
						|
- \-J--add-exports=java.base/jdk.internal.foreign.abi=ALL-UNNAMED
 | 
						|
- \-J--add-exports=java.base/jdk.internal.foreign.layout=ALL-UNNAMED
 | 
						|
- \-J--add-exports=java.base/jdk.internal.foreign=ALL-UNNAMED
 | 
						|
- \-J--enable-native-access=ALL-UNNAMED
 | 
						|
 | 
						|
If you are running kawa.jar with plain java then give same arguments to java
 | 
						|
without the -J prefix.
 | 
						|
 | 
						|
### Installation
 | 
						|
<a name="installation"></a>
 | 
						|
 | 
						|
Since the project is under active development is best to clone it from git,
 | 
						|
 | 
						|
### Project local
 | 
						|
<a name="installation-project-local"></a>
 | 
						|
 | 
						|
#### Linux
 | 
						|
<a name="installation-project-local-linux"></a>
 | 
						|
Assuming you have a project and your libraries live in directory called snow
 | 
						|
in it:
 | 
						|
 | 
						|
    git clone https://git.sr.ht/~retropikzel/r7rs-pffi
 | 
						|
    mkdir -p snow
 | 
						|
    cp -r r7rs-pffi/retropikzel snow/
 | 
						|
    cd snow/retropikzel/pffi
 | 
						|
    make <SCHEME>
 | 
						|
 | 
						|
#### Windows
 | 
						|
<a name="installation-project-local-windows"></a>
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
### System global
 | 
						|
<a name="installation-system-global"></a>
 | 
						|
 | 
						|
Still work in progress.
 | 
						|
 | 
						|
## Reference
 | 
						|
<a name="reference"></a>
 | 
						|
 | 
						|
### Types
 | 
						|
<a name="types"></a>
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
### Types
 | 
						|
<a name="types"></a>
 | 
						|
 | 
						|
### Environment variables
 | 
						|
<a name="environment-variables"></a>
 | 
						|
 | 
						|
Setting environment variables like this on Windows works for this library:
 | 
						|
 | 
						|
    set "PFFI_LOAD_PATH=C:\Program Files (x86)/foo/bar"
 | 
						|
 | 
						|
#### PFFI\_LOAD\_PATH
 | 
						|
<a name="environment-variables-pffi-load-path"></a>
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
### Procedures and macros
 | 
						|
<a name="procedures-and-macros"></a>
 | 
						|
 | 
						|
Some of these are procedures and some macros, it might also change implementation to implementation.
 | 
						|
 | 
						|
#### pffi-init
 | 
						|
<a name="pffi-init"></a>
 | 
						|
 | 
						|
**pffi-init**
 | 
						|
 | 
						|
Always call this first, on most implementation it does nothing but some implementations might need
 | 
						|
initialisation run.
 | 
						|
 | 
						|
#### c-size-of
 | 
						|
<a name="c-size-of"></a>
 | 
						|
 | 
						|
**c-size-of** object -> number
 | 
						|
 | 
						|
Returns the size of the pffi-struct, pffi-enum or pffi-type.
 | 
						|
 | 
						|
#### pffi-align-of
 | 
						|
<a name="pffi-align-of"></a>
 | 
						|
 | 
						|
**pffi-align-of** type -> number
 | 
						|
 | 
						|
Returns the align of the type.
 | 
						|
 | 
						|
#### define-c-library
 | 
						|
<a name="define-c-library"></a>
 | 
						|
 | 
						|
**define-c-library** headers shared-object-name [options] -> object
 | 
						|
 | 
						|
Load given shared object automatically searching many predefined paths.
 | 
						|
 | 
						|
Takes as argument a list of C headers, these are for the compiler ones. And an shared-object name,
 | 
						|
used by the dynamic FFI's. The name of the shared object should not contain suffix like .so or
 | 
						|
.dll. Nor should it contain any prefix like "lib".
 | 
						|
 | 
						|
Additional options argument can be provided, theys should be a pair with a
 | 
						|
keyword. The options are:
 | 
						|
 | 
						|
- additional-versions
 | 
						|
    - 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.
 | 
						|
    - Can be either numbers or strings
 | 
						|
- additional-paths
 | 
						|
    - Give additional paths to search shared objects for
 | 
						|
 | 
						|
Example:
 | 
						|
 | 
						|
    (cond-expand
 | 
						|
      (windows (define-c-library libc-stdlib
 | 
						|
                                    '("stdlib.h")
 | 
						|
                                    "ucrtbase"
 | 
						|
                                    '((additional-versions ("0" "6"))
 | 
						|
                                      (additiona-paths (".")))))
 | 
						|
      (else (define-c-library libc-stdlib
 | 
						|
                                 (list "stdlib.h")
 | 
						|
                                 "c"
 | 
						|
                                 '((additional-versions ("0" "6"))
 | 
						|
                                   (additiona-paths ("."))))))
 | 
						|
 | 
						|
#### Notes
 | 
						|
 | 
						|
- Do not cond-expand inside the arguments, that might lead to problems on some
 | 
						|
implementations.
 | 
						|
- Do not store options in variables, that might lead to problems on some
 | 
						|
implementations.
 | 
						|
- Do pass the headers using quote
 | 
						|
    - As '(... and not (list...
 | 
						|
- Do pass the options using quote
 | 
						|
    - As '(... and not (list...
 | 
						|
 | 
						|
#### make-c-null
 | 
						|
<a name="make-c-null"></a>
 | 
						|
 | 
						|
**make-c-null** -> pointer
 | 
						|
 | 
						|
Returns a new NULL pointer.
 | 
						|
 | 
						|
#### c-null?
 | 
						|
<a name="is-c-null"></a>
 | 
						|
 | 
						|
**c-null?** pointer -> boolean
 | 
						|
 | 
						|
Returns #t if given pointer is null pointer, #f otherwise.
 | 
						|
 | 
						|
#### make-c-bytevector
 | 
						|
<a name="make-c-bytevector "></a>
 | 
						|
 | 
						|
(make-c-bytevector *k*)
 | 
						|
(make-c-bytevector *k* *fill*)
 | 
						|
 | 
						|
Returns a newly allocated C bytevector(pointer) of length k. If byte is given,
 | 
						|
then all elements of the C bytevector are initialized to byte, otherwise the
 | 
						|
contents of each element are unspecified.
 | 
						|
 | 
						|
#### pffi-pointer-address
 | 
						|
<a name="pffi-pointer-address"></a>
 | 
						|
 | 
						|
**pffi-pointer-address** pointer -> pointer
 | 
						|
 | 
						|
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
 | 
						|
c's &. One **important difference** 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:
 | 
						|
 | 
						|
    (define input-pointer (make-c-bytevector <needed size>))
 | 
						|
    (define input-pointer-address (pffi-pointer-address input-pointer))
 | 
						|
    (<foreign-procedure-that takes &pointer as argument> input-pointer-address)
 | 
						|
    (set! input-pointer (pffi-pointer-get input-pointer-address 'pointer 0))
 | 
						|
 | 
						|
#### c-bytevector?
 | 
						|
<a name="pffi-pointer"></a>
 | 
						|
 | 
						|
**c-bytevector?** object -> boolean
 | 
						|
 | 
						|
Returns #t if given object is pointer, #f otherwise.
 | 
						|
 | 
						|
#### c-free
 | 
						|
<a name="c-free"></a>
 | 
						|
 | 
						|
**c-free** pointer
 | 
						|
 | 
						|
Frees given pointer.
 | 
						|
 | 
						|
#### pffi-pointer-set!
 | 
						|
<a name="pffi-pointer-set!"></a>
 | 
						|
 | 
						|
**pffi-pointer-set!** pointer type offset value
 | 
						|
 | 
						|
Sets the value on a pointer on given offset. For example:
 | 
						|
 | 
						|
    (define p (make-c-bytevector 128))
 | 
						|
    (pffi-pointer-set! p 'int 64 100)
 | 
						|
 | 
						|
Would set the offset of 64, on pointer p to value 100.
 | 
						|
 | 
						|
#### pffi-pointer-get
 | 
						|
<a name="pffi-pointer-get"></a>
 | 
						|
 | 
						|
**pffi-pointer-get** pointer type offset -> object
 | 
						|
 | 
						|
Gets the value from a pointer on given offset. For example:
 | 
						|
 | 
						|
    (define p (make-c-bytevector 128))
 | 
						|
    (pffi-pointer-set! p 'int 64 100)
 | 
						|
    (pffi-pointer-get p 'int 64)
 | 
						|
    > 100
 | 
						|
 | 
						|
#### utf8->c-bytevector
 | 
						|
<a name="utf8-into-c-bytevector"></a>
 | 
						|
 | 
						|
**utf8->c-bytevector** string -> pointer
 | 
						|
 | 
						|
Makes pointer out of a given string.
 | 
						|
 | 
						|
#### c-bytevector->string
 | 
						|
<a name="c-bytevector-into-string"></a>
 | 
						|
 | 
						|
**c-bytevector->sring** pointer -> string
 | 
						|
 | 
						|
Makes string out of a given pointer.
 | 
						|
 | 
						|
#### pffi-struct-make
 | 
						|
<a name="pffi-struct-make"></a>
 | 
						|
 | 
						|
**pffi-struct-make** c-type members . pointer -> pffi-struct
 | 
						|
 | 
						|
Creates a new pffi-struct and allocates pointer for it. The members argument is a list of member
 | 
						|
names and types. For example:
 | 
						|
 | 
						|
    (define color (pffi-struct-make 'color '((int8 . r) (int8 . g) (int8 . b) (int8 .a ))))
 | 
						|
    (define test (pffi-struct-make "struct test" '((int8 . r) (int8 . g) (int8 . b) (int8 .a ))))
 | 
						|
 | 
						|
C-type argument can be symbol or a string.
 | 
						|
 | 
						|
#### pffi-struct-pointer
 | 
						|
<a name="pffi-struct-pointer"></a>
 | 
						|
 | 
						|
**pffi-struct-pointer** pffi-struct -> pointer
 | 
						|
 | 
						|
Returns the pointer that holds the struct content. You need to use this when passing a struct as
 | 
						|
a pointer to foreign functions.
 | 
						|
 | 
						|
    (define s (pffi-struct-make 'test '((int . r) (int . g) (int . b))))
 | 
						|
    (pffi-struct-pointer s)
 | 
						|
 | 
						|
#### pffi-struct-offset-get
 | 
						|
<a name="pffi-struct-offset-get"></a>
 | 
						|
 | 
						|
**pffi-struct-offset-get** member-name -> number
 | 
						|
 | 
						|
Returns the offset of a struct member with given name.
 | 
						|
 | 
						|
#### pffi-struct-get
 | 
						|
<a name="pffi-struct-get"></a>
 | 
						|
 | 
						|
**pffi-struct-get** pffi-struct member-name -> object
 | 
						|
 | 
						|
Returns the value of the givens struct member.
 | 
						|
 | 
						|
#### pffi-struct-set!
 | 
						|
<a name="pffi-struct-set!"></a>
 | 
						|
 | 
						|
**pffi-struct-set!** pffi-struct member-name value
 | 
						|
 | 
						|
Sets the value of the givens struct member. It is up to you to make sure that the type of value is
 | 
						|
correct.
 | 
						|
 | 
						|
#### pffi-array-allocate
 | 
						|
<a name="pffi-array-allocate"></a>
 | 
						|
 | 
						|
**pffi-array-allocate** type size
 | 
						|
 | 
						|
Allocates pointer array of given type and size.
 | 
						|
 | 
						|
#### pffi-array-pointer
 | 
						|
<a name="pffi-array-pointer"></a>
 | 
						|
 | 
						|
**pffi-array-pointer** array
 | 
						|
 | 
						|
Returns the pointer of the array.
 | 
						|
 | 
						|
#### pffi-array?
 | 
						|
<a name="pffi-array"></a>
 | 
						|
 | 
						|
**pffi-array?** object
 | 
						|
 | 
						|
Returns #t of given object is array, #f otherwise.
 | 
						|
 | 
						|
#### pffi-pointer->array
 | 
						|
<a name="pffi-pointer->array"></a>
 | 
						|
 | 
						|
**pffi-pointer->array** pointer type size
 | 
						|
 | 
						|
Converts given pointer to an array of giben type and size.
 | 
						|
 | 
						|
#### pffi-array-get
 | 
						|
<a name="pffi-array-get"></a>
 | 
						|
 | 
						|
**pffi-array-get** array index
 | 
						|
 | 
						|
Returns the value of given index from given array.
 | 
						|
 | 
						|
#### pffi-array-set!
 | 
						|
<a name="pffi-array-set!"></a>
 | 
						|
 | 
						|
**pffi-array-set!** array index value
 | 
						|
 | 
						|
Sets the given value of given index in given array.
 | 
						|
 | 
						|
#### pffi-list->array
 | 
						|
<a name="pffi-list->array"></a>
 | 
						|
 | 
						|
**pffi-list->array** type list
 | 
						|
 | 
						|
Converts given list into C array of given type.
 | 
						|
 | 
						|
#### pffi-array->list
 | 
						|
<a name="pffi-array->list"></a>
 | 
						|
 | 
						|
**pffi-array->list** type list length
 | 
						|
 | 
						|
Converts given C array into list of given type and length.
 | 
						|
 | 
						|
#### define-c-procedure
 | 
						|
<a name="define-c-procedure"></a>
 | 
						|
 | 
						|
**define-c-procedure** scheme-name shared-object c-name return-type argument-types
 | 
						|
 | 
						|
Defines a new foreign function to be used from Scheme code. For example:
 | 
						|
 | 
						|
    (cond-expand
 | 
						|
        (windows (define-c-library libc-stdlib '("stdlib.h") "ucrtbase" '("")))
 | 
						|
        (else (define-c-library libc-stdlib '("stdlib.h")  "c" '("" "6"))))
 | 
						|
    (define-c-procedure c-puts libc-stdlib 'puts 'int '(pointer))
 | 
						|
    (c-puts "Message brought to you by FFI!")
 | 
						|
 | 
						|
#### pffi-define-callback
 | 
						|
<a name="pffi-define-callback"></a>
 | 
						|
 | 
						|
**pffi-define-callback** scheme-name return-type argument-types procedure
 | 
						|
 | 
						|
Defines a new Sceme function to be used as callback to C code. For example:
 | 
						|
 | 
						|
    ; Load the shared library
 | 
						|
    (cond-expand
 | 
						|
        (windows (define-c-library libc-stdlib '("stdlib.h") "ucrtbase" '()))
 | 
						|
        (else (define-c-library '("stdlib.h") "c" '("" "6"))))
 | 
						|
 | 
						|
    ; Define C function that takes a callback
 | 
						|
    (define-c-procedure qsort libc-stdlib 'qsort 'void '(pointer int int callback))
 | 
						|
 | 
						|
    ; Define our callback
 | 
						|
    (pffi-define-callback compare
 | 
						|
                          'int
 | 
						|
                          '(pointer pointer)
 | 
						|
                          (lambda (pointer-a pointer-b)
 | 
						|
                            (let ((a (pffi-pointer-get pointer-a 'int 0))
 | 
						|
                                  (b (pffi-pointer-get pointer-b 'int 0)))
 | 
						|
                              (cond ((> a b) 1)
 | 
						|
                                    ((= a b) 0)
 | 
						|
                                    ((< a b) -1)))))
 | 
						|
 | 
						|
    ; Create new array of ints to be sorted
 | 
						|
    (define array (make-c-bytevector (* (c-size-of 'int) 3)))
 | 
						|
    (pffi-pointer-set! array 'int (* (c-size-of 'int) 0) 3)
 | 
						|
    (pffi-pointer-set! array 'int (* (c-size-of 'int) 1) 2)
 | 
						|
    (pffi-pointer-set! array 'int (* (c-size-of 'int) 2) 1)
 | 
						|
 | 
						|
    (display array)
 | 
						|
    (newline)
 | 
						|
    ;> (3 2 1)
 | 
						|
 | 
						|
    ; Sort the array
 | 
						|
    (qsort array 3 (c-size-of 'int) compare)
 | 
						|
 | 
						|
    (display array)
 | 
						|
    (newline)
 | 
						|
    ;> (1 2 3)
 | 
						|
 | 
						|
</main>
 |