[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Dynamic Foreign Function Interface with dynamic-link*
From: |
Amirouche Boubekki |
Subject: |
Dynamic Foreign Function Interface with dynamic-link* |
Date: |
Sun, 21 Feb 2016 16:28:01 +0100 |
User-agent: |
Roundcube Webmail/1.1.2 |
Héllo everyone!
I created a `dynamic-link*` procedure to help during the creation of
dynamic ffi bindings (which is the prefered way to go now on).
It's helpful for several reasons:
- no need to explicitly call `dynamic-func` and `pointer->procedure`,
so it's two less procedures to know about.
- It mimicks the C signature, so it's easier to read.
This documentation is meant to be self sufficient which means that you
should be able to fully bind your favorite *function based* C library
just by reading this.
The code of the procedure is at the bottom.
## `((dynamic-link* [library-name]) return-type function-name .
arguments)`
Return a lambda that returns a scheme procedure linked against
FUNCTION-NAME found in LIBRARY-NAME. If LIBRARY-NAME is not provided
this links against the C standard library.
The returned procedure takes the signature of the function that you
want to link against.
RETURN-TYPE and ARGUMENTS must be foreign types. They can be found in
`(system foreign)` [1]:
- int8
- uint8
- uint16
- int16
- uint32
- int32
- uint64
- int64
- float
- double
In addition, platform-dependent types variables exists:
- int
- unsigned-int
- long
- unsigned-long
- size_t
- ssize_t
- ptrdiff_t
There is also a `void` variable that must be used to wrap
function that returns nothing.
Last but not least, the symbol `'*` is used by convention
to denote pointer types.
[1]
https://www.gnu.org/software/guile/manual/html_node/Foreign-Types.html#Foreign-Types
## Example
Here is a REPL run, showing how it works:
```scheme
(define stdlib (dynamic-link*)) ;; link against stdlib
(define strlen (stdlib int "strlen" '*)) ;; retrieve a procedure
associated to "strlen"
(strlen (string->pointer "abc"))
```
Since you probably don't want to expose the pointer api
to the dev. You might define the following `strlen` procedure:
```scheme
(define stdlib (dynamic-link*)) ;; link against stdlib
(define (strlen string)
(let ((function (stdlib (int "strlen" '*)))) ;; retrieve strlen
function as a procedure
(function (string->pointer string))))
```
AFAIK, there is no performance gain in memoizing `stdlib`.
## Where to go from here?
If you need to bind structures the proper way to go is to use scheme
bytestructures [2].
[2] https://github.com/TaylanUB/scheme-bytestructures
## The code
```scheme
(use-modules (system foreign))
(define* (dynamic-link* #:optional library-name)
(let ((shared-object (if library-name (dynamic-link library-name)
(dynamic-link))))
(lambda (return-value function-name . arguments)
(let ((function (dynamic-func function-name shared-object)))
(pointer->procedure return-value function arguments)))))
```
HTH!
--
Amirouche ~ amz3 ~ http://www.hypermove.net
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Dynamic Foreign Function Interface with dynamic-link*,
Amirouche Boubekki <=