1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><title>Foreign Types</title><meta name="generator" content="DocBook XSL Stylesheets V1.62.4" /><link rel="home" href="index.html" title="SBCL User Manual" /><link rel="up" href="ffi.html" title="Chapter5.The Foreign Function Interface" /><link rel="previous" href="ffi.html" title="Chapter5.The Foreign Function Interface" /><link rel="next" href="foreign-values.html" title="Operations On Foreign Values" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Foreign Types</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ffi.html">Prev</a></td><th width="60%" align="center">Chapter5.The Foreign Function Interface</th><td width="20%" align="right"><a accesskey="n" href="foreign-values.html">Next</a></td></tr></table><hr /></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="foreign-types"></a>Foreign Types</h2></div></div><div></div></div><p>Alien types have a description language based on nested list
structure. For example the C type
</p><pre class="programlisting">struct foo {
int a;
struct foo *b[100];
};</pre><p>
has the corresponding <span class="application">SBCL</span> FFI type
</p><pre class="programlisting">(struct foo
(a int)
(b (array (* (struct foo)) 100)))</pre><p>
</p><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id2933778"></a>Defining Foreign Types</h3></div></div><div></div></div><p>
Types may be either named or anonymous. With structure and union
types, the name is part of the type specifier, allowing recursively
defined types such as:
</p><pre class="programlisting">(struct foo (a (* (struct foo))))</pre><p>
An anonymous structure or union type is specified by using the name
<tt class="literal">nil</tt>. The <tt class="function">with-alien</tt> macro defines a local
scope which “<span class="quote">captures</span>” any named type definitions. Other types
are not inherently named, but can be given named abbreviations using
the <tt class="function">define-alien-type</tt> macro.
</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id2933813"></a>Foreign Types and Lisp Types</h3></div></div><div></div></div><p>
The foreign types form a subsystem of the <span class="application">SBCL</span> type system. An
<tt class="type">alien</tt> type specifier provides a way to use any foreign type as a
Lisp type specifier. For example,
</p><pre class="programlisting">(typep foo '(alien (* int)))</pre><p>
can be used to determine whether <tt class="varname">foo</tt> is a pointer to a foreign
<tt class="type">int</tt>. <tt class="type">alien</tt> type specifiers can be used in the same ways
as ordinary Lisp type specifiers (like <tt class="type">string</tt>.) Alien type
declarations are subject to the same
precise type checking
as any other declaration.
</p><p>
Note that the type identifiers used in the
foreign type system overlap with native Lisp type
specifiers in some cases. For example, the type specifier
<tt class="type">(alien single-float)</tt> is identical to <tt class="type">single-float</tt>, since
foreign floats are automatically converted to Lisp floats. When
<tt class="function">type-of</tt> is called on an alien value that is not automatically
converted to a Lisp value, then it will return an <tt class="type">alien</tt> type
specifier.
</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id2936865"></a>Foreign Type Specifiers</h3></div></div><div></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
All foreign type names are exported from the <tt class="literal">sb-alien</tt>
package. Some foreign type names are also symbols in
the <tt class="literal">common-lisp</tt> package, in which case they are
reexported from the <tt class="literal">sb-alien</tt> package, so that
e.g. it is legal to refer to <tt class="type">sb-alien:single-float</tt>.
</p></div><p>
These are the basic foreign type specifiers:
</p><div class="itemizedlist"><ul type="disc"><li><p>
The foreign type specifier <tt class="type">(* foo)</tt> describes a
pointer to an object of type <tt class="type">foo</tt>. A pointed-to type
<tt class="type">foo</tt> of <tt class="type">t</tt> indicates a pointer to anything,
similar to <tt class="type">void *</tt> in ANSI C. A null alien pointer can
be detected with the <tt class="function">sb-alien:null-alien</tt>
function.
</p></li><li><p>
The foreign type specifier <tt class="type">(array foo &optional dimensions)</tt>
describes array of the specified <tt class="literal">dimensions</tt>, holding
elements of type <tt class="type">foo</tt>. Note that (unlike in C) <tt class="type">(* foo)</tt>
<tt class="type">(array foo)}</tt> are considered to be different types when
type checking is done. If equivalence of pointer and array types
is desired, it may be explicitly coerced using
<tt class="function">sb-alien:cast</tt>.
</p><p>
Arrays are accessed using <tt class="function">sb-alien:deref</tt>, passing
the indices as additional arguments. Elements are stored in
column-major order (as in C), so the first dimension determines
only the size of the memory block, and not the layout of the
higher dimensions. An array whose first dimension is variable
may be specified by using <tt class="literal">nil</tt> as the first dimension.
Fixed-size arrays can be allocated as array elements, structure
slots or <tt class="function">sb-alien:with-alien</tt> variables. Dynamic
arrays can only be allocated using <tt class="function">sb-alien:make-alien</tt>.
</p></li><li><p>
The foreign type specifier
<tt class="type">(sb-alien:struct name &rest fields)</tt>
describes a structure type with the specified <tt class="varname">name</tt> and
<tt class="varname">fields</tt>. Fields are allocated at the same offsets
used by the implementation's C compiler. If <tt class="varname">name</tt>
is <tt class="literal">nil</tt> then the structure is anonymous.
</p><p>
If a named foreign <tt class="type">struct</tt> specifier is passed to
<tt class="function">define-alien-type</tt> or <tt class="function">with-alien</tt>,
then this defines, respectively, a new global or local foreign
structure type. If no <tt class="varname">fields</tt> are specified, then
the fields are taken from the current (local or global) alien
structure type definition of <tt class="varname">name</tt>.
</p></li><li><p>
The foreign type specifier
<tt class="type">(sb-alien:union name &rest fields)</tt>
is similar to <tt class="type">sb-alien:struct</tt>, but describes a union type.
All fields are allocated at the same offset, and the size of the
union is the size of the largest field. The programmer must
determine which field is active from context.
</p></li><li><p>
The foreign type specifier <tt class="type">(sb-alien:enum name &rest specs)</tt>
describes an enumeration type that maps between integer values
and keywords. If <tt class="varname">name</tt> is <tt class="literal">nil</tt>, then the
type is anonymous. Each element of the <tt class="varname">specs</tt>
list is either a Lisp keyword, or a list <tt class="literal">(keyword value)</tt>.
<tt class="varname">value</tt> is an integer. If <tt class="varname">value</tt> is not
supplied, then it defaults to one greater than the value for
the preceding spec (or to zero if it is the first spec.)
</p></li><li><p>
The foreign type specifier <tt class="type">(sb-alien:signed &optional bits)</tt>
specifies a signed integer with the specified number of
<tt class="varname">bits</tt> precision. The upper limit on integer
precision is determined by the machine's word
size. If <tt class="varname">bits</tt> is not specified, the maximum
size will be used.
</p></li><li><p>
The foreign type specifier <tt class="type">(integer &optional bits)</tt> is
equivalent to the corresponding type specifier using
<tt class="type">sb-alien:signed</tt> instead of <tt class="type">integer</tt>.
</p></li><li><p>
The foreign type specifier
<tt class="type">(sb-alien:unsigned &optional bits)</tt>
is like corresponding type specifier using <tt class="type">sb-alien:signed</tt>
except that the variable is treated as an unsigned integer.
</p></li><li><p>
The foreign type specifier <tt class="type">(boolean &optional bits)</tt> is
similar to an enumeration type, but maps from Lisp <tt class="literal">nil</tt>
and <tt class="literal">t</tt> to C <tt class="literal">0</tt> and <tt class="literal">1</tt>
respectively. <tt class="varname">bits</tt> determines the amount of
storage allocated to hold the truth value.
</p></li><li><p>
The foreign type specifier <tt class="type">single-float</tt> describes a
floating-point number in IEEE single-precision format.
</p></li><li><p>
The foreign type specifier <tt class="type">double-float</tt> describes a
floating-point number in IEEE double-precision format.
</p></li><li><p>
The foreign type specifier
<tt class="type">(function result-type &rest arg-types)</tt>
describes a foreign function that takes arguments of the specified
<tt class="varname">arg-types</tt> and returns a result of type <tt class="type">result-type</tt>.
Note that the only context where a foreign <tt class="type">function</tt> type
is directly specified is in the argument to
<tt class="function">sb-alien:alien-funcall</tt>.
In all other contexts, foreign functions are represented by
foreign function pointer types: <tt class="type">(* (function ...))</tt>.
</p></li><li><p>
The foreign type specifier <tt class="type">sb-alien:system-area-pointer</tt>
describes a pointer which is represented in Lisp as a
<tt class="type">system-area-pointer</tt> object. <span class="application">SBCL</span> exports this type from
<tt class="literal">sb-alien</tt> because <span class="application">CMU CL</span> did, but tentatively (as of
the first draft of this section of the manual, <span class="application">SBCL</span> 0.7.6) it is
deprecated, since it doesn't seem to be required by user code.
</p></li><li><p>
The foreign type specifier <tt class="type">sb-alien:void</tt> is
used in function types to declare that no useful value
is returned. Using <tt class="function">alien-funcall</tt>
to call a <tt class="type">void</tt> foreign function will return
zero values.
</p></li><li><p>
The foreign type specifier <tt class="type">sb-alien:c-string</tt>
is similar to <tt class="type">(* char)</tt>, but is interpreted as a
null-terminated string, and is automatically converted into a
Lisp string when accessed; or if the pointer is C <tt class="literal">NULL</tt>
or <tt class="literal">0</tt>, then accessing it gives Lisp <tt class="literal">nil</tt>.
Lisp strings are stored with a trailing NUL termination, so no
copying (either by the user or the implementation) is necessary
when passing them to foreign code.
</p><p>
Assigning a Lisp string to a <tt class="type">c-string</tt> structure field or
variable stores the contents of the string to the memory already
pointed to by that variable. When a foreign object of type
<tt class="type">(* char)</tt> is assigned to a <tt class="type">c-string</tt>, then the
<tt class="type">c-string</tt> pointer is assigned to. This allows
<tt class="type">c-string</tt> pointers to be initialized. For example:
</p><pre class="programlisting">(cl:in-package "CL-USER") ; which USEs package "SB-ALIEN"
(define-alien-type nil (struct foo (str c-string)))
(defun make-foo (str) (let ((my-foo (make-alien (struct foo))))
(setf (slot my-foo 'str) (make-alien char (length str))
(slot my-foo 'str) str) my-foo))</pre><p>
Storing Lisp <tt class="literal">NIL</tt> in a <tt class="type">c-string</tt> writes C
<tt class="literal">NULL</tt> to the variable.
</p></li><li><p>
<tt class="literal">sb-alien</tt> also exports translations of these C type
specifiers as foreign type specifiers:
<tt class="type">sb-alien:char</tt>,
<tt class="type">sb-alien:short</tt>,
<tt class="type">sb-alien:int</tt>,
<tt class="type">sb-alien:long</tt>,
<tt class="type">sb-alien:unsigned-char</tt>,
<tt class="type">sb-alien:unsigned-short</tt>,
<tt class="type">sb-alien:unsigned-int</tt>,
<tt class="type">sb-alien:unsigned-long</tt>,
<tt class="type">sb-alien:float</tt>, and
<tt class="type">sb-alien:double</tt>.
</p></li></ul></div><p>
</p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ffi.html">Prev</a></td><td width="20%" align="center"><a accesskey="u" href="ffi.html">Up</a></td><td width="40%" align="right"><a accesskey="n" href="foreign-values.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter5.The Foreign Function Interface</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">Operations On Foreign Values</td></tr></table></div></body></html>
|