docs: Expands docs around C function pointers (#1038)

* docs: Generates HTML docs for Function core module

* docs: Adds lifetime information in Function module

* docs: Adds callback section to C Interop

* docs: Corrects typos in Function docs
This commit is contained in:
Tim Dévé 2020-12-01 09:44:03 +00:00 committed by GitHub
parent 2a94f67db8
commit ac4231d005
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 4 deletions

View File

@ -1,7 +1,16 @@
(defmodule Function
(doc unsafe-ptr "returns void pointer to the function passed in."
"This is unsafe as unsafe-ptr can't check the value passed in is a function.")
(doc unsafe-ptr "returns a void pointer to the function passed in.
This is unsafe as unsafe-ptr can't check the value passed in is a function.
It is the responsibility of the caller to ensure that the lifetime of the pointer
does not exceed the lifetime of the function it's used on.")
(deftemplate unsafe-ptr (Fn [(Ref a)] (Ptr ())) "void* $NAME($a *fn)" "$DECL { return fn->callback; }")
(doc unsafe-env-ptr "returns void pointer to the environment captured by a lambda."
"This is unsafe as unsafe-env-ptr can't check the value passed in is a function.")
(doc unsafe-env-ptr "returns void pointer to the environment captured by a lambda.
This is unsafe as unsafe-env-ptr can't check the value passed in is a function.
It is the responsibility of the caller to ensure that the lifetime of the pointer
does not exceed the lifetime of the function it's used on.")
(deftemplate unsafe-env-ptr (Fn [(Ref a)] (Ptr ())) "void* $NAME($a *fn)" "$DECL { return fn->env; }"))

View File

@ -12,6 +12,7 @@ This is an extension of what is covered in the [Language Guide](./LanguageGuide.
- [`deftemplate`](#deftemplate)
- [`Basic example`](#basic-example)
- [`Generics`](#generics)
- [Callbacks](#callbacks)
## How Carp generates identifiers
@ -342,3 +343,44 @@ out/main.c:9153:29: error: invalid operands to binary expression ('String' (aka
1 error generated.
```
## Callbacks
Some C APIs rely on callbacks, let's define a C function that accepts a
callback and an argument and returns the result of calling that function as an
example:
```clojure
(deftemplate runner (Fn [(Ptr ()) (Ptr ())] a)
"$a $NAME(void* fnptr, void* args)"
"$DECL {
return (($a(*)(void*))fnptr)(args);
}")
; Using a lambda capturing variables from its environment
(let [x 20 y 22 fnfn (fn [] (+ @&x @&y))]
(= (runner (Function.unsafe-ptr &fnfn) (Function.unsafe-env-ptr &fnfn))
42))
; Using a static function
(defn double [x] (Int.* @x 2))
(let [x 42]
(= (runner (Function.unsafe-ptr &double) (Unsafe.coerce &x))
84))
```
In the first example we want to use a lambda capturing some variable, we can
use `Function.unsafe-ptr` to get a `void*` to the function and in the case of
lambdas capturing environment the first argument to that function is the
environment so we have to use `Function.unsafe-env-ptr` to pass in that
environment.
In the second example we want to use a static function so we can use
`Function.unsafe-ptr` again, and the argument we pass in needs to be coerced
from a `Ref` into a `(Ptr ())`.
Because everything gets turned into a void pointer all type safety is lost so
it is the responsibility of the caller to ensure the operation is safe. It is
also important to ensure the lifetime of the `Ptr` doesn't not exceed the
lifetime of the function/env it represents.

View File

@ -21,6 +21,7 @@
Double
Dynamic
Float
Function
Geometry
Int
IO