File: foreign-types.html

package info (click to toggle)
sbcl 1%3A0.8.16-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 15,028 kB
  • ctags: 14,790
  • sloc: lisp: 194,656; ansic: 16,544; asm: 2,060; sh: 1,674; makefile: 199
file content (196 lines) | stat: -rw-r--r-- 14,222 bytes parent folder | download
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 &#8220;<span class="quote">captures</span>&#8221; 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 &amp;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 &amp;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 &amp;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 &amp;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 &amp;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 &amp;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 &amp;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 &amp;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 &amp;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 &quot;CL-USER&quot;) ; which USEs package &quot;SB-ALIEN&quot;
        (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>