mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-03-13 08:20:31 -07:00
new-doc: ffi: uffi step
This commit is contained in:
parent
5a6ae92846
commit
ca3697b6ef
4 changed files with 338 additions and 50 deletions
|
|
@ -1,5 +1,7 @@
|
|||
@node Foreign Function Interface
|
||||
@section Foreign Function Interface
|
||||
@cindex Foreign function interface
|
||||
@ftindex FFI
|
||||
|
||||
@menu
|
||||
* What is a FFI? :: FFI introduciton
|
||||
|
|
@ -8,12 +10,11 @@
|
|||
* Higher level interfaces :: Usage examples
|
||||
* SFFI Reference :: Static FFI reference
|
||||
@c * LFFI Reference :: Library FFI reference
|
||||
* DFFI Reference :: Dynamic FFI reference
|
||||
@c * DFFI Reference :: Dynamic FFI reference
|
||||
* UFFI Reference :: UFFI reference manual
|
||||
@end menu
|
||||
|
||||
@node What is a FFI?
|
||||
@cindex Foreign function interface
|
||||
@subsection What is a FFI?
|
||||
A Foreign Function Interface, or FFI for short, is a means for a programming language to
|
||||
interface with libraries written in other programming languages, the foreign code. You will
|
||||
|
|
@ -298,5 +299,5 @@ Build and load this module with (compile-file "ecl.lsp" :load t)
|
|||
@end lisp
|
||||
|
||||
@include extensions/ffi_sffi.txi
|
||||
@node DFFI Reference
|
||||
@c @include extensions/ffi_dffi.txi
|
||||
@include extensions/ffi_uffi.txi
|
||||
|
|
|
|||
|
|
@ -2,20 +2,19 @@
|
|||
@subsection SFFI Reference
|
||||
@cindex C/C++ code inlining
|
||||
|
||||
@subsubheading @code{ffi:clines} — Insert C declarations and definitions
|
||||
@lspindex ffi:clines
|
||||
@defspec ffi:clines c/c++-code*
|
||||
|
||||
Insert C declarations and definitions
|
||||
|
||||
@table @var
|
||||
@item c/c++-code
|
||||
One or more strings with C definitions. Not evaluated.
|
||||
@item returns
|
||||
No value.
|
||||
@end table
|
||||
@end defspec
|
||||
|
||||
@strong{Description}
|
||||
|
||||
@subsubheading Description
|
||||
This special form inserts C code from strings passed in the
|
||||
@var{arguments} directly in the file that results from compiling lisp
|
||||
sources. Contrary to @code{ffi:c-inline}, this function may have no
|
||||
|
|
@ -30,8 +29,7 @@ beginning of the produced header file.
|
|||
compiled files as a toplevel form. Other uses will lead to an error
|
||||
being signaled, either at the compilation time or when loading the file.
|
||||
|
||||
@strong{Examples}
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:clines} adding c toplevel declarations
|
||||
In this example the FFI:CLINES statement is required to get access to
|
||||
the C function @code{cos}:
|
||||
|
|
@ -40,12 +38,14 @@ the C function @code{cos}:
|
|||
(defun cos (x)
|
||||
(ffi:c-inline (x) (:double) :double "cos(#0)" :on-liner t))
|
||||
@end lisp
|
||||
@end defspec
|
||||
|
||||
@subsubheading @code{ffi:c-inline} — Inline C code in a lisp form
|
||||
@lspindex ffi:c-inline
|
||||
@defspec ffi:c-inline (lisp-values) (arg-c-types) return-type c/c++-code @
|
||||
&key (side-effects t) (one-liner nil)
|
||||
|
||||
Inline C code in a lisp form
|
||||
|
||||
@table @var
|
||||
@item lisp-values
|
||||
One or more lisp expressions. Evaluated.
|
||||
|
|
@ -64,10 +64,8 @@ T.
|
|||
@item returns
|
||||
One or more lisp values.
|
||||
@end table
|
||||
@end defspec
|
||||
|
||||
@strong{Description}
|
||||
|
||||
@subsubheading Description
|
||||
This is a special form which can be only used in compiled code and whose
|
||||
purpose is to execute some C code getting and returning values from and
|
||||
to the lisp environment.
|
||||
|
|
@ -105,8 +103,7 @@ Note that the conversion between lisp arguments and FFI types is
|
|||
automatic. Note also that @code{ffi:c-inline} cannot be used in
|
||||
interpreted or bytecompiled code! Such usage will signal an error.
|
||||
|
||||
@strong{Examples}
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:c-inline} inlining c code
|
||||
The following example implements the transcendental function SIN using
|
||||
the C equivalent:
|
||||
|
|
@ -152,27 +149,27 @@ and two output values:
|
|||
:side-effects nil))
|
||||
@end verbatim
|
||||
@end lisp
|
||||
@end defspec
|
||||
|
||||
@subsubheading ffi:c-progn – Interleave C statements with the Lisp code
|
||||
@lspindex ffi:c-progn
|
||||
@defspec ffi:c-progn args &body body
|
||||
|
||||
Interleave C statements with the Lisp code
|
||||
|
||||
@table @var
|
||||
@item args
|
||||
Lisp arguments. Evaluated.
|
||||
@item returns
|
||||
No value.
|
||||
@end table
|
||||
@end defspec
|
||||
|
||||
@strong{Description}
|
||||
|
||||
@subsubheading Description
|
||||
This form is used for it's side effects. It allows for interleaving C
|
||||
statements with the Lisp code. The argument types doesn't have to be
|
||||
declared – in such case the objects type in the C world will be
|
||||
@code{cl_object}.
|
||||
|
||||
@strong{Examples}
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:c-progn} interleaving c and lisp code
|
||||
@lisp
|
||||
@verbatim
|
||||
|
|
@ -189,57 +186,60 @@ declared – in such case the objects type in the C world will be
|
|||
"}")))
|
||||
@end verbatim
|
||||
@end lisp
|
||||
@end defspec
|
||||
|
||||
@c XXX: SFFI returns one-element list pointer, while DFFI returns just a
|
||||
@c pointer. This is probably a bug.
|
||||
|
||||
@subsubheading ffi:defcallback
|
||||
@lspindex ffi:defcallback
|
||||
@defspec ffi:defcallback name ret-type arg-desc &body body
|
||||
|
||||
@table @var
|
||||
|
||||
@item name
|
||||
Name of the lisp function.
|
||||
|
||||
@item ret-type
|
||||
Declaration of the return type which function returns.
|
||||
|
||||
@item arg-desc
|
||||
List of pairs @code{(arg-name arg-type)}.
|
||||
|
||||
@item body
|
||||
Function body.
|
||||
|
||||
@item returns
|
||||
Pointer to the defined callback.
|
||||
|
||||
@end table
|
||||
@end defspec
|
||||
|
||||
@strong{Description}
|
||||
|
||||
@subsubheading Description
|
||||
Defines Lisp function and generates a callback for the C world, which
|
||||
may be passed to these functions. Note, that this special operator has
|
||||
also a dynamic variant (with the same name and interface).
|
||||
@end defspec
|
||||
|
||||
@subsubheading ffi:defcbody
|
||||
@lspindex ffi:defcbody
|
||||
@defmac ffi:defcbody name arg-types result-type c-expression
|
||||
@end defmac
|
||||
|
||||
@strong{Description}
|
||||
Define C function under the lisp name
|
||||
|
||||
@table @var
|
||||
@item name
|
||||
Defined function name.
|
||||
@item arg-types
|
||||
Argument types of the defined Lisp function.
|
||||
@item result-type
|
||||
Result type of the C function (may be @code{(values ...)}.
|
||||
@item returns
|
||||
Defined function name.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
The compiler defines a Lisp function named by NAME whose body consists
|
||||
of the C code of the string C-EXPRESSION. In the C-EXPRESSION one can
|
||||
reference the arguments of the function as @code{#0}, @code{#1}, etc.
|
||||
|
||||
The interpreter ignores this form. ARG-TYPES are argument types of the
|
||||
defined Lisp function and RESULT-TYPE is its return type.
|
||||
The interpreter ignores this form.
|
||||
@end defmac
|
||||
|
||||
@subsubheading ffi:defentry
|
||||
@lspindex ffi:defentry
|
||||
@defmac ffi:defentry name arg-types c-name &key no-interrupts
|
||||
|
||||
@table @var
|
||||
@item name
|
||||
Lisp name for the function.
|
||||
|
|
@ -257,21 +257,19 @@ name is @code{(STRING C-NAME)}.
|
|||
|
||||
@item returns
|
||||
Lisp function @code{NAME}.
|
||||
|
||||
@end table
|
||||
@end defmac
|
||||
|
||||
@strong{Description}
|
||||
|
||||
@subsubheading Description
|
||||
The compiler defines a Lisp function named by NAME whose body consists
|
||||
of a calling sequence to the C language function named by FUNCTION-NAME.
|
||||
|
||||
The interpreter ignores this form. ARG-TYPES are argument types of the
|
||||
C function and RESULT-TYPE is its return type. Symbols OBJECT, INT,
|
||||
CHAR, CHAR*, FLOAT, DOUBLE are allowed for these types.
|
||||
@end defmac
|
||||
|
||||
@c XXX> note sure if this works
|
||||
@c @subsubheading ffi:definline
|
||||
@c @subsubheading @code{definline}
|
||||
@c @lspindex ffi:definline
|
||||
@c @defmac ffi:definline fun arg-types result-type code
|
||||
@c @table @var
|
||||
|
|
@ -282,20 +280,19 @@ CHAR, CHAR*, FLOAT, DOUBLE are allowed for these types.
|
|||
@c @end table
|
||||
@c @end defmac
|
||||
|
||||
@c @strong{Description}
|
||||
|
||||
@c @subsubheading Description
|
||||
@c DEFINLINE behaves like a DEFCBODY (see), but also instructs the LISP
|
||||
@c compiler to expand inline any call to function SYMBOL into code
|
||||
@c corresponding to the C language expression C/C++-CODE, whenever it can
|
||||
@c determine that the actual arguments are of the specified type.
|
||||
@c <XXX
|
||||
|
||||
@subsubheading ffi:defla
|
||||
@lspindex ffi:defla
|
||||
@defmac ffi:defla name lambda-list &body body
|
||||
@end defmac
|
||||
@defmac ffi:defla name args &body body
|
||||
|
||||
@strong{Description}
|
||||
Provide Lisp alternative for interpreted code.
|
||||
|
||||
@subsubheading Description
|
||||
Used to DEFine Lisp Alternative. For the interpreter, DEFLA is equivalent to
|
||||
DEFUN, but the compiler ignores this form.
|
||||
@end defmac
|
||||
|
|
|
|||
|
|
@ -2,9 +2,297 @@
|
|||
@subsection UFFI Reference
|
||||
|
||||
@menu
|
||||
@c * Primitive Types
|
||||
@c * Aggregate Types
|
||||
* Primitive Types ::
|
||||
* Aggregate Types ::
|
||||
@c * Objects
|
||||
@c * Strings
|
||||
@c * Functions and Libraries
|
||||
@end menu
|
||||
|
||||
@node Primitive Types
|
||||
@subsubsection Primitive Types
|
||||
@cindex Foreign primitive types
|
||||
|
||||
@subsubheading Overview
|
||||
Primitive types have a single value, these include characters, numbers,
|
||||
and pointers. They are all symbols in the keyword package.
|
||||
|
||||
@lspindex :char
|
||||
@lspindex :unsigned-char
|
||||
@lspindex :byte
|
||||
@lspindex :unsigned-byte
|
||||
@lspindex :short
|
||||
@lspindex :unsigned-short
|
||||
@lspindex :int
|
||||
@lspindex :unsigned-int
|
||||
@lspindex :long
|
||||
@lspindex :unsigned-long
|
||||
@lspindex :int16_t
|
||||
@lspindex :uint16_t
|
||||
@lspindex :int32_t
|
||||
@lspindex :uint32_t
|
||||
@lspindex :int64_t
|
||||
@lspindex :uint64_t
|
||||
@lspindex :float
|
||||
@lspindex :double
|
||||
@c @lspindex :long-double
|
||||
@lspindex :cstring
|
||||
@lspindex :void
|
||||
@lspindex :pointer-void
|
||||
@lspindex :*
|
||||
|
||||
@ftindex LONG-LONG
|
||||
@ftindex UINT16-T
|
||||
@ftindex UINT32-T
|
||||
@ftindex UINT64-T
|
||||
@ftindex LONG-FLOAT
|
||||
|
||||
@table @samp
|
||||
@item :char
|
||||
@itemx :unsigned-char
|
||||
Signed/unsigned 8-bits. Dereferenced pointer returns a character.
|
||||
@item :byte
|
||||
@itemx :unsigned-byte
|
||||
Signed/unsigned 8-bits. Dereferenced pointer returns an integer.
|
||||
@item :short
|
||||
@itemx :unsigned-short
|
||||
@itemx :int
|
||||
@itemx :unsigned-int
|
||||
@itemx :long
|
||||
@itemx :unsigned-long
|
||||
Standard integer types (16-bit, 32-bit and 32/64-bit).
|
||||
@item :int16_t
|
||||
@itemx :uint16_t
|
||||
@itemx :int32_t
|
||||
@itemx :uint32_t
|
||||
@itemx :int64_t
|
||||
@itemx :uint64_t
|
||||
Integer types with guaranteed bitness.
|
||||
|
||||
@item :float
|
||||
@itemx :double
|
||||
Floating point numerals (32-bit and 64-bit).
|
||||
@c XXX>
|
||||
@c @item :long-double
|
||||
@c Floating point numeral (usually 80-bit, at least 64-bit, exact
|
||||
@c bitness is compiler/architecture/platform dependant).
|
||||
@c XXX<
|
||||
@item :cstring
|
||||
A @code{NULL} terminated string used for passing and returning
|
||||
characters strings with a C function.
|
||||
@item :void
|
||||
The absence of a value. Used to indicate that a function does not return
|
||||
a value.
|
||||
@item :pointer-void
|
||||
Points to a generic object.
|
||||
@item *
|
||||
Used to declare a pointer to an object.
|
||||
@end table
|
||||
|
||||
|
||||
@lspindex ffi:def-constant
|
||||
@defmac ffi:def-constant name value &key (export nil)
|
||||
|
||||
Binds a symbol to a constant.
|
||||
|
||||
@table @var
|
||||
@item name
|
||||
A symbol that will be bound to the value.
|
||||
@item value
|
||||
An evaluated form that is bound the the name.
|
||||
@item export
|
||||
When @code{T}, the name is exported from the current package. Defaults
|
||||
to @code{NIL}.
|
||||
@item returns
|
||||
Constant name.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
This is a thin wrapper around @code{defconstant}. It evaluates at
|
||||
compile-time and optionally exports the symbol from the package.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-constant} defining constants
|
||||
@lisp
|
||||
(ffi:def-constant pi2 (* 2 pi))
|
||||
(ffi:def-constant exported-pi2 (* 2 pi) :export t)
|
||||
@end lisp
|
||||
|
||||
@subsubheading Side Effects
|
||||
Creats a new special variable.
|
||||
@end defmac
|
||||
|
||||
|
||||
|
||||
@lspindex ffi:def-foreign-type
|
||||
@defmac ffi:def-foreign-type name definition
|
||||
|
||||
Defines a new foreign type
|
||||
|
||||
@table @var
|
||||
@item name
|
||||
A symbol naming the new foreign type.
|
||||
@item value
|
||||
A form that is not evaluated that defines the new foreign type.
|
||||
@item returns
|
||||
Foreign type designator (@var{value}).
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
Defines a new foreign type
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-foreign-type} examples
|
||||
@lisp
|
||||
(def-foreign-type my-generic-pointer :pointer-void)
|
||||
(def-foreign-type a-double-float :double-float)
|
||||
(def-foreign-type char-ptr (* :char))
|
||||
@end lisp
|
||||
|
||||
@subsubheading Side effects
|
||||
Defines a new foreign type.
|
||||
@end defmac
|
||||
|
||||
|
||||
|
||||
@lspindex ffi:null-char-p
|
||||
@defmac ffi:null-char-p char
|
||||
|
||||
Tests a character for NULL value
|
||||
|
||||
@table @var
|
||||
@item char
|
||||
A character or integer.
|
||||
@item returns
|
||||
A boolean flag indicating if @var{char} is a NULL value.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
A predicate testing if a character or integer is NULL. This abstracts
|
||||
the difference in implementations where some return a character and some
|
||||
return a integer whence dereferencing a C character pointer.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:null-char-p} example
|
||||
@lisp
|
||||
(ffi:def-array-pointer ca :unsigned-char)
|
||||
(let ((fs (ffi:convert-to-foreign-string "ab")))
|
||||
(values (ffi:null-char-p (ffi:deref-array fs 'ca 0))
|
||||
(ffi:null-char-p (ffi:deref-array fs 'ca 2))))
|
||||
;; => NIL T
|
||||
@end lisp
|
||||
@end defmac
|
||||
|
||||
|
||||
|
||||
@node Aggregate Types
|
||||
@subsubsection Aggregate Types
|
||||
@cindex Foreign aggregate types
|
||||
|
||||
@subsubheading Overview
|
||||
Aggregate types are comprised of one or more primitive types.
|
||||
|
||||
|
||||
@lspindex ffi:def-enum
|
||||
@defmac ffi:def-enum name fields &key separator-key
|
||||
|
||||
Defines a C enumeration
|
||||
|
||||
@table @var
|
||||
@item name
|
||||
A symbol that names the enumeration.
|
||||
@item fields
|
||||
A list of field defintions. Each definition can be a symbol or a list of
|
||||
two elements. Symbols get assigned a value of the current counter which
|
||||
starts at 0 and increments by 1 for each subsequent symbol. It the field
|
||||
definition is a list, the first position is the symbol and the second
|
||||
position is the value to assign the the symbol. The current counter gets
|
||||
set to 1+ this value.
|
||||
@item returns
|
||||
A string that governs the creation of constants. The default is "#".
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
Declares a C enumeration. It generates constants with integer values for
|
||||
the elements of the enumeration. The symbols for the these constant
|
||||
values are created by the concatenation of the enumeration name,
|
||||
separator-string, and field symbol. Also creates a foreign type with the
|
||||
name name of type :int.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-enum} sample enumerations
|
||||
@lisp
|
||||
(ffi:def-enum abc (:a :b :c))
|
||||
;; Creates constants abc#a (1), abc#b (2), abc#c (3) and defines
|
||||
;; the foreign type "abc" to be :int
|
||||
|
||||
(ffi:def-enum efoo (:e1 (:e2 10) :e3) :separator-string "-")
|
||||
;; Creates constants efoo-e1 (1), efoo-e2 (10), efoo-e3 (11) and defines
|
||||
;; the foreign type efoo to be :int
|
||||
@end lisp
|
||||
|
||||
@subsubheading Side effects
|
||||
Creates a @code{:int} foreign type, defines constants.
|
||||
@end defmac
|
||||
|
||||
|
||||
|
||||
@defmac ffi:def-struct name &rest fields
|
||||
|
||||
Defines a C structure
|
||||
|
||||
@table @var
|
||||
@item name
|
||||
A symbol that names the structure.
|
||||
@item fields
|
||||
A variable number of field defintions. Each definition is a list
|
||||
consisting of a symbol naming the field followed by its foreign type.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
Declares a structure. A special type is available as a slot in the
|
||||
field. It is a pointer that points to an instance of the parent
|
||||
structure. It's type is @code{:pointer-self}.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-struct} defining C structure
|
||||
@lisp
|
||||
(ffi:def-struct foo (a :unsigned-int)
|
||||
(b (* :char))
|
||||
(c (:array :int 10))
|
||||
(next :pointer-self))
|
||||
@end lisp
|
||||
|
||||
@subsubheading Side effects
|
||||
Creates a foreign type.
|
||||
@end defmac
|
||||
|
||||
|
||||
|
||||
@lspindex ffi:get-slot-value
|
||||
@defmac ffi:get-slot-value obj type field
|
||||
|
||||
Retrieves a value from a slot of a structure
|
||||
|
||||
@table @var
|
||||
@item obj
|
||||
A pointer to foreign structure.
|
||||
@item type
|
||||
A name of the foreign structure.
|
||||
@item field
|
||||
A name of the desired field in foreign structure.
|
||||
@item returns
|
||||
The value of the @code{field} in the structure @code{obj}.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
Accesses a slot value from a structure. This is generalized and can be
|
||||
used with @code{setf}.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:get-slot-value} getting and setting C structure field
|
||||
@lisp
|
||||
(get-slot-value foo-ptr 'foo-structure 'field-name)
|
||||
(setf (get-slot-value foo-ptr 'foo-structure 'field-name) 10)
|
||||
@end lisp
|
||||
@end defmac
|
||||
|
|
|
|||
|
|
@ -73,3 +73,5 @@ Many nodes, moderate amount of content (deviations from the standard)
|
|||
(ffi:definline …)
|
||||
#+END_SRC
|
||||
|
||||
* Things to fix
|
||||
- [ ] Add :long-double to the UFFI interface
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue