2442 lines
111 KiB
HTML
2442 lines
111 KiB
HTML
|
<!DOCTYPE html>
|
|||
|
<html>
|
|||
|
<!-- Created by GNU Texinfo 7.0.3, https://www.gnu.org/software/texinfo/ -->
|
|||
|
<head>
|
|||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|||
|
<title>Foreign Function Interface (ECL Manual)</title>
|
|||
|
|
|||
|
<meta name="description" content="Foreign Function Interface (ECL Manual)">
|
|||
|
<meta name="keywords" content="Foreign Function Interface (ECL Manual)">
|
|||
|
<meta name="resource-type" content="document">
|
|||
|
<meta name="distribution" content="global">
|
|||
|
<meta name="Generator" content="makeinfo">
|
|||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|||
|
|
|||
|
<link href="index.html" rel="start" title="Top">
|
|||
|
<link href="Indexes.html" rel="index" title="Indexes">
|
|||
|
<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
|
|||
|
<link href="Extensions.html" rel="up" title="Extensions">
|
|||
|
<link href="Native-threads.html#Native-threads" rel="next" title="Native threads">
|
|||
|
<link href="Operating-System-Interface.html#Operating-System-Interface" rel="prev" title="Operating System Interface">
|
|||
|
<style type="text/css">
|
|||
|
<!--
|
|||
|
/* colors */
|
|||
|
|
|||
|
a.copiable-link {visibility: hidden; text-decoration: none; line-height: 0em}
|
|||
|
div.example {margin-left: 3.2em}
|
|||
|
span.r {font-family: initial; font-weight: normal; font-style: normal}
|
|||
|
span:hover a.copiable-link {visibility: visible}
|
|||
|
strong.def-name {font-family: monospace; font-weight: bold; font-size: larger}
|
|||
|
ul.mark-bullet {list-style-type: disc}
|
|||
|
@media (prefers-color-scheme: dark) {
|
|||
|
/* dark theme */
|
|||
|
html { color: seashell;
|
|||
|
background: #1A1A1A; }
|
|||
|
body { background: #1A1A1A; }
|
|||
|
th { border-bottom: 2px solid lightgray; }
|
|||
|
h1, h2, h3, h4, h5 { background-image: linear-gradient(to left, #202020, #3A3A3A); }
|
|||
|
code, var, code a { color: darkorange;
|
|||
|
background: #2A2A2A; }
|
|||
|
a { color: seashell; }
|
|||
|
pre { background: #2A2A2A;
|
|||
|
color: seashell;
|
|||
|
/* mark longer code block with stripe on the left */
|
|||
|
border-left: 5px solid darkorange;
|
|||
|
padding-left: 10px; }
|
|||
|
pre.screen { background: #2A2A2A;
|
|||
|
border: 1px solid lightgray; }
|
|||
|
pre.programlisting { background: #2A2A2A;
|
|||
|
border-left: 1px solid lightgray;
|
|||
|
border-top: 1px solid lightgray; }
|
|||
|
/* we need a light background in order for the images to be readable */
|
|||
|
img { background: white }
|
|||
|
}
|
|||
|
@media (prefers-color-scheme: light) {
|
|||
|
/* light theme */
|
|||
|
html { background: white }
|
|||
|
body { background: white }
|
|||
|
th { border-bottom: 2px solid gray; }
|
|||
|
h1, h2, h3, h4, h5 { background: lightgray; }
|
|||
|
code, var, code a { color: darkred;
|
|||
|
background: whitesmoke; }
|
|||
|
a { color: #000; }
|
|||
|
pre { background: whitesmoke;
|
|||
|
color: black;
|
|||
|
/* mark longer code block with stripe on the left */
|
|||
|
border-left: 5px solid darkred;
|
|||
|
padding-left: 10px; }
|
|||
|
pre.screen { background: #EEE;
|
|||
|
border: 1px solid black; }
|
|||
|
pre.programlisting { background: #EEEEEE;
|
|||
|
border-left: 1px solid black;
|
|||
|
border-top: 1px solid black; }
|
|||
|
}
|
|||
|
|
|||
|
body {
|
|||
|
margin: 1em 125px 0 10%;
|
|||
|
line-height: 1.5em;
|
|||
|
padding: 0 2em 1em 2em;
|
|||
|
font: 13px Verdana,Arial, sans-serif
|
|||
|
}
|
|||
|
ul, dd, dl, dt { margin-top: 0; margin-bottom: 0; }
|
|||
|
p, code, td, dl, dt {
|
|||
|
line-height: 1.5em;
|
|||
|
}
|
|||
|
table {
|
|||
|
font: inherit;
|
|||
|
border-collapse: collapse;
|
|||
|
}
|
|||
|
th, td {
|
|||
|
vertical-align: top;
|
|||
|
}
|
|||
|
h1, h2, h3 { padding-left: 15px; }
|
|||
|
h4, h5 { padding-left: 5px; }
|
|||
|
code, pre {
|
|||
|
font-size: 1em;
|
|||
|
font-family: monospace;
|
|||
|
}
|
|||
|
var {
|
|||
|
font-size: 1em;
|
|||
|
}
|
|||
|
/* links inside code appear the same as the code itself */
|
|||
|
code a {
|
|||
|
font-weight: normal;
|
|||
|
text-decoration: none;
|
|||
|
}
|
|||
|
/* but get an underline when hovering */
|
|||
|
code a:hover {
|
|||
|
text-decoration: underline;
|
|||
|
}
|
|||
|
/* ordinary links appear in bold */
|
|||
|
a { font-weight: bold; }
|
|||
|
pre.verbatim {
|
|||
|
margin: 0 0 0 0;
|
|||
|
}
|
|||
|
pre {
|
|||
|
overflow: auto;
|
|||
|
}
|
|||
|
pre.screen {
|
|||
|
font-weight: bold;
|
|||
|
padding: 0.5em;
|
|||
|
}
|
|||
|
pre.programlisting {
|
|||
|
padding: 0.5em;
|
|||
|
}
|
|||
|
div p { padding: 0 2em }
|
|||
|
li p { padding: 0; margin: 0 }
|
|||
|
hr { display: none; }
|
|||
|
div.funcsynopsis p {
|
|||
|
text-indent: -2em;
|
|||
|
}
|
|||
|
div.variablelist {
|
|||
|
padding: 0 2em;
|
|||
|
}
|
|||
|
.type, .funcsynopsis, .symbol {
|
|||
|
font-family: monospace;
|
|||
|
}
|
|||
|
.type, .symbol, .replaceable {
|
|||
|
white-space: nowrap;
|
|||
|
}
|
|||
|
|
|||
|
-->
|
|||
|
</style>
|
|||
|
|
|||
|
|
|||
|
</head>
|
|||
|
|
|||
|
<body lang="en">
|
|||
|
<div class="section-level-extent" id="Foreign-Function-Interface">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Native-threads.html#Native-threads" accesskey="n" rel="next">Native threads</a>, Previous: <a href="Operating-System-Interface.html#Operating-System-Interface" accesskey="p" rel="prev">Operating System Interface</a>, Up: <a href="Extensions.html" accesskey="u" rel="up">Extensions</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h3 class="section" id="Foreign-Function-Interface-1">3.3 Foreign Function Interface</h3>
|
|||
|
<a class="index-entry-id" id="index-Foreign-function-interface"></a>
|
|||
|
<a class="index-entry-id" id="index-FFI"></a>
|
|||
|
|
|||
|
|
|||
|
<ul class="mini-toc">
|
|||
|
<li><a href="Foreign-Function-Interface.html#What-is-a-FFI_003f" accesskey="1">What is a FFI?</a></li>
|
|||
|
<li><a href="Foreign-Function-Interface.html#Two-kinds-of-FFI" accesskey="2">Two kinds of FFI</a></li>
|
|||
|
<li><a href="Foreign-Function-Interface.html#Foreign-objects" accesskey="3">Foreign objects</a></li>
|
|||
|
<li><a href="Foreign-Function-Interface.html#Higher-level-interfaces" accesskey="4">Higher level interfaces</a></li>
|
|||
|
<li><a href="Foreign-Function-Interface.html#SFFI-Reference" accesskey="5">SFFI Reference</a></li>
|
|||
|
<li><a href="Foreign-Function-Interface.html#DFFI-Reference" accesskey="6">DFFI Reference</a></li>
|
|||
|
<li><a href="Foreign-Function-Interface.html#UFFI-Reference" accesskey="7">UFFI Reference</a></li>
|
|||
|
</ul>
|
|||
|
<hr>
|
|||
|
<div class="subsection-level-extent" id="What-is-a-FFI_003f">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Foreign-Function-Interface.html#Two-kinds-of-FFI" accesskey="n" rel="next">Two kinds of FFI</a>, Up: <a href="Foreign-Function-Interface.html#Foreign-Function-Interface" accesskey="u" rel="up">Foreign Function Interface</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsection" id="What-is-a-FFI_003f-1">3.3.1 What is a FFI?</h4>
|
|||
|
<p>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
|
|||
|
see this concept most often being used in interpreted environments, such as Python, Ruby or
|
|||
|
Lisp, where one wants to reuse the big number of libraries written in C and C++ for dealing
|
|||
|
with graphical interfaces, networking, filesystems, etc.
|
|||
|
</p>
|
|||
|
<p>A FFI is made of at least three components:
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><em class="dfn">Foreign objects management</em></dt>
|
|||
|
<dd><p>This is the data that the foreign code will use. A FFI needs to provide
|
|||
|
means to build and manipulate foreign data, with automatic conversions
|
|||
|
to and from lisp data types whenever possible, and it also has to deal
|
|||
|
with issues like garbage collection and finalization.
|
|||
|
</p></dd>
|
|||
|
<dt><em class="dfn">Foreign code loader</em></dt>
|
|||
|
<dd><p>To actually use a foreign routine, the code must reside in memory. The
|
|||
|
process of loading this code and finding out the addresses of the
|
|||
|
routines we want to use is normally done by an independent component.
|
|||
|
</p></dd>
|
|||
|
<dt><em class="dfn">Foreign function invocation</em></dt>
|
|||
|
<dd><p>This is the part of the FFI that deals with actually calling the foreign
|
|||
|
routines we want to use. For that one typically has to tell the FFI what
|
|||
|
are the arguments that these routines expect, what are the calling
|
|||
|
conventions and where are these routines to be found.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p>On top of these components sits a higher level interface written
|
|||
|
entirely in lisp, with which you will actually declare and use foreign
|
|||
|
variables, functions and libraries. In the following sections we
|
|||
|
describe both the details of the low-level components (See <a class="xref" href="Foreign-Function-Interface.html#Two-kinds-of-FFI">Two kinds of FFI</a> and <a class="ref" href="Foreign-Function-Interface.html#Foreign-objects">Foreign objects</a>), and of the higher level interface
|
|||
|
(See <a class="xref" href="Foreign-Function-Interface.html#Higher-level-interfaces">Higher level interfaces</a>). It is highly recommended that you read
|
|||
|
all sections.
|
|||
|
</p>
|
|||
|
<hr>
|
|||
|
</div>
|
|||
|
<div class="subsection-level-extent" id="Two-kinds-of-FFI">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Foreign-Function-Interface.html#Foreign-objects" accesskey="n" rel="next">Foreign objects</a>, Previous: <a href="Foreign-Function-Interface.html#What-is-a-FFI_003f" accesskey="p" rel="prev">What is a FFI?</a>, Up: <a href="Foreign-Function-Interface.html#Foreign-Function-Interface" accesskey="u" rel="up">Foreign Function Interface</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsection" id="Two-kinds-of-FFI-1">3.3.2 Two kinds of FFI</h4>
|
|||
|
<a class="index-entry-id" id="index-Two-kinds-of-FFI"></a>
|
|||
|
<p>ECL allows for two different approaches when building a FFI. Both
|
|||
|
approaches have a different implementation philosophy and affect the
|
|||
|
places where you can use the FFI and how.
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><em class="dfn">Static FFI (SFFI)</em></dt>
|
|||
|
<dd><p>For every foreign function and variable you might need to use, a wrapper
|
|||
|
is automatically written in C with the help of ffi:c-inline. These
|
|||
|
wrappers are compiled using an ordinary C compiler and linked against
|
|||
|
both the foreign libraries you want to use and against the ECL
|
|||
|
library. The result is a FASL file that can be loaded from ECL and where
|
|||
|
the wrappers appear as ordinary lisp functions and variables that the
|
|||
|
user may directly invoked.
|
|||
|
</p>
|
|||
|
|
|||
|
</dd>
|
|||
|
<dt id='index-_002d_002dwith_002dlibffi_002dprefix_003dpath'><span><em class="dfn">Dynamic FFI (DFFI)</em><a class="copiable-link" href='Foreign-Function-Interface.html#index-_002d_002dwith_002dlibffi_002dprefix_003dpath'> ¶</a></span></dt>
|
|||
|
<dd><a class="index-entry-id" id="index-_002d_002dwith_002ddffi-_005bsystem_007cincluded_007cAUTO_007cno_005d"></a>
|
|||
|
|
|||
|
<p>First of all, the foreign libraries are loaded in memory using the
|
|||
|
facilities of the operating system. Similar routines are used to find
|
|||
|
out and register the memory location of all the functions and variables
|
|||
|
we want to use. Finally, when actually accessing these functions, a
|
|||
|
little piece of assembly code does the job of translating the lisp data
|
|||
|
into foreign objects, storing the arguments in the stack and in CPU
|
|||
|
registers, calling the function and converting back the output of the
|
|||
|
function to lisp.
|
|||
|
</p>
|
|||
|
<p>ECL for this purpose utilizes
|
|||
|
<em class="emph"><a class="uref" href="https://sourceware.org/libffi/">libffi</a></em>, a portable
|
|||
|
foreign-function interface library.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<div class="float" id="fig_003affi_005fcomponents">
|
|||
|
|
|||
|
<img class="image" src="figures/ffi.png" alt="figures/ffi">
|
|||
|
<div class="caption"><p><strong class="strong">Figure 3.2: </strong>FFI components</p></div></div>
|
|||
|
<p>As you see, the first approach uses rather portable techniques based on a
|
|||
|
programming language (C, C++) which is strongly supported by the
|
|||
|
operating system. The conversion of data is performed by a calling
|
|||
|
routines in the ECL library and we need not care about the precise
|
|||
|
details (organizing the stack, CPU registers, etc) when calling a
|
|||
|
function: the compiler does this for us.
|
|||
|
</p>
|
|||
|
<p>On the other hand, the dynamic approach allows us to choose the
|
|||
|
libraries we load at any time, look for the functions and invoke them
|
|||
|
even from the toplevel, but it relies on unportable techniques and
|
|||
|
requires the developers to know very well both the assembly code of the
|
|||
|
machine the code runs on and the calling conventions of that particular
|
|||
|
operating system. For these reasons ECL doesn’t maintain it’s own
|
|||
|
implementation of the DFFI but rather relies on the third party library.
|
|||
|
</p>
|
|||
|
<p>ECL currently supports the static method on all platforms, and the
|
|||
|
dynamical one a wide range of the most popular ones, shown in the
|
|||
|
section <em class="emph">Supported Platforms</em> at
|
|||
|
<a class="url" href="https://sourceware.org/libffi/">https://sourceware.org/libffi/</a>.
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-DFFI"></a>
|
|||
|
<p>You can test if your copy of ECL was built with DFFI by inspecting
|
|||
|
whether the symbol <code class="code">:dffi</code> is present in the list from variable
|
|||
|
<code class="code">*features*</code>.
|
|||
|
</p>
|
|||
|
<hr>
|
|||
|
</div>
|
|||
|
<div class="subsection-level-extent" id="Foreign-objects">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Foreign-Function-Interface.html#Higher-level-interfaces" accesskey="n" rel="next">Higher level interfaces</a>, Previous: <a href="Foreign-Function-Interface.html#Two-kinds-of-FFI" accesskey="p" rel="prev">Two kinds of FFI</a>, Up: <a href="Foreign-Function-Interface.html#Foreign-Function-Interface" accesskey="u" rel="up">Foreign Function Interface</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsection" id="Foreign-objects-1">3.3.3 Foreign objects</h4>
|
|||
|
|
|||
|
<p>While the foreign function invocation protocols differ strongly between
|
|||
|
platforms and implementations, foreign objects are pretty easy to handle
|
|||
|
portably. For ECL, a foreign object is just a bunch of bytes stored in
|
|||
|
memory. The lisp object for a foreign object encapsulates several bits
|
|||
|
of information:
|
|||
|
</p>
|
|||
|
<ul class="itemize mark-bullet">
|
|||
|
<li>A list or a symbol specifying the C type of the object.
|
|||
|
</li><li>The pointer to the region of memory where data is stored.
|
|||
|
</li><li>A flag determining whether ECL can automatically manage that piece of
|
|||
|
memory and deallocated when no longer in use.
|
|||
|
</li></ul>
|
|||
|
|
|||
|
<p>A foreign object may contain many different kinds of data: integers,
|
|||
|
floating point numbers, C structures, unions, etc. The actual type of
|
|||
|
the object is stored in a list or a symbol which is understood by the
|
|||
|
higher level interface (See <a class="xref" href="Foreign-Function-Interface.html#Higher-level-interfaces">Higher level interfaces</a>).
|
|||
|
</p>
|
|||
|
<p>The most important component of the object is the memory region where
|
|||
|
data is stored. By default ECL assumes that the user will perform
|
|||
|
manual management of this memory, deleting the object when it is no
|
|||
|
longer needed. The first reason is that this block may have been
|
|||
|
allocated by a foreign routine using <code class="code">malloc()</code>, or
|
|||
|
<code class="code">mmap()</code>, or statically, by referring to a C constant. The second
|
|||
|
reason is that foreign functions may store references to this memory
|
|||
|
which ECL is not aware of and, in order to keep these references
|
|||
|
valid, ECL should not attempt to automatically destroy the object.
|
|||
|
</p>
|
|||
|
<p>In many cases, however, it is desirable to automatically destroy foreign
|
|||
|
objects once they have been used. The higher level interfaces UFFI and
|
|||
|
<a class="url" href="https://common-lisp.net/project/cffi/">CFFI</a> provide tools for doing
|
|||
|
this. For instance, in the following example adapted from the UFFI
|
|||
|
documentation, the string <var class="var">name</var> is automatically deallocated
|
|||
|
</p>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-function ("gethostname" c-gethostname)
|
|||
|
((name (* :unsigned-char))
|
|||
|
(len :int))
|
|||
|
:returning :int)
|
|||
|
|
|||
|
(ffi:with-foreign-object (name '(:array :unsigned-char 256))
|
|||
|
(if (zerop (c-gethostname (ffi:char-array-to-pointer name) 256))
|
|||
|
(format t "Hostname: ~S" (ffi:convert-from-foreign-string name))
|
|||
|
(error "gethostname() failed.")))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<ul class="mini-toc">
|
|||
|
<li><a href="Foreign-Function-Interface.html#C-Reference-23" accesskey="1">C Reference</a></li>
|
|||
|
</ul>
|
|||
|
<div class="subsubsection-level-extent" id="C-Reference-23">
|
|||
|
<h4 class="subsubsection">3.3.3.1 C Reference</h4>
|
|||
|
|
|||
|
<a class="index-entry-id" id="index-ecl_005fmake_005fpointer"></a>
|
|||
|
<a class="anchor" id="ecl_005fmake_005fforeign_005fdata"></a><a class="index-entry-id" id="index-ecl_005fmake_005fforeign_005fdata"></a>
|
|||
|
<dl class="first-deftypefn first-deftypefun-alias-first-deftypefn">
|
|||
|
<dt class="deftypefn deftypefun-alias-deftypefn" id="index-ecl_005fmake_005fforeign_005fdata-1"><span class="category-def">Function: </span><span><code class="def-type">cl_object</code> <strong class="def-name">ecl_make_foreign_data</strong> <code class="def-code-arguments">(cl_object tag, cl_index size, void *data)</code><a class="copiable-link" href='Foreign-Function-Interface.html#index-ecl_005fmake_005fforeign_005fdata-1'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>This function creates a Lisp “foreign object” that points to a C data. Use
|
|||
|
this function to pass a data from C to Lisp.
|
|||
|
</p>
|
|||
|
<p><var class="var">tag</var> denotes the data type (See <a class="xref" href="Foreign-Function-Interface.html#Primitive-Types">Primitive Types</a>)
|
|||
|
<var class="var">size</var> is a number of elements in <var class="var">data</var> (or 0 for a raw pointer)
|
|||
|
<var class="var">data</var> is a pointer to C data (either an object or an array)
|
|||
|
</p>
|
|||
|
<p>The C macro <code class="code">ecl_make_pointer(pointer)</code> expands to
|
|||
|
<code class="code">ecl_make_foreign_data(ECL_NIL, 0, (pointer))</code>.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ecl_005fto_005fpointer"></a><a class="index-entry-id" id="index-ecl_005fto_005fpointer"></a>
|
|||
|
<a class="anchor" id="ecl_005fforeign_005fdata_005fpointer_005fsafe"></a><a class="index-entry-id" id="index-ecl_005fforeign_005fdata_005fpointer_005fsafe"></a>
|
|||
|
<dl class="first-deftypefn first-deftypefun-alias-first-deftypefn">
|
|||
|
<dt class="deftypefn deftypefun-alias-deftypefn" id="index-_002aecl_005fforeign_005fdata_005fpointer_005fsafe_0028cl_005fobject"><span class="category-def">Function: </span><span><code class="def-type">void</code> <strong class="def-name">*ecl_foreign_data_pointer_safe(cl_object</strong> <code class="def-code-arguments">f)</code><a class="copiable-link" href='Foreign-Function-Interface.html#index-_002aecl_005fforeign_005fdata_005fpointer_005fsafe_0028cl_005fobject'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>This function returns a C pointer for the given Lisp foreign object. Lisp
|
|||
|
foreign objects are constructed with functions <code class="code">ecl_make_foreign_data</code>
|
|||
|
and <code class="code">ecl_allocate_foreign_data</code>.
|
|||
|
</p>
|
|||
|
<p>The wrapper created with <code class="code">ecl_make_foreign_data</code> is a subject of
|
|||
|
garbage collection, but the pointer itself is not “freed”, because
|
|||
|
the data producer is “C world” and the consumer is “Lisp world”.
|
|||
|
</p>
|
|||
|
<p>This is different from <code class="code">si:allocate-foreign-object</code> where the
|
|||
|
data producer is “Lisp world” and the consumer is “C world”. In
|
|||
|
that case the wrapper is not collected unless explicitly released with
|
|||
|
<code class="code">si:free-foreign-object</code> in which case the allocated foreign data
|
|||
|
is also released.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ecl_005fbase_005fstring_005fpointer_005fsafe"></a><a class="index-entry-id" id="index-ecl_005fbase_005fstring_005fpointer_005fsafe"></a>
|
|||
|
|
|||
|
<dl class="first-deftypefn first-deftypefun-alias-first-deftypefn">
|
|||
|
<dt class="deftypefn deftypefun-alias-deftypefn" id="index-_002aecl_005fbase_005fstring_005fpointer_005fsafe_0028cl_005fobject"><span class="category-def">Function: </span><span><code class="def-type">char</code> <strong class="def-name">*ecl_base_string_pointer_safe(cl_object</strong> <code class="def-code-arguments">f)</code><a class="copiable-link" href='Foreign-Function-Interface.html#index-_002aecl_005fbase_005fstring_005fpointer_005fsafe_0028cl_005fobject'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>This function returns a pointer to a simple base string <var class="var">f</var>. If <var class="var">f</var> is
|
|||
|
not a simple base string this function signals an error.
|
|||
|
</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ecl_005fnull_005fterminated_005fbase_005fstring"></a><a class="index-entry-id" id="index-ecl_005fnull_005fterminated_005fbase_005fstring"></a>
|
|||
|
<dl class="first-deftypefn first-deftypefun-alias-first-deftypefn">
|
|||
|
<dt class="deftypefn deftypefun-alias-deftypefn" id="index-ecl_005fnull_005fterminated_005fbase_005fstring_0028cl_005fobject"><span class="category-def">Function: </span><span><code class="def-type">cl_object</code> <strong class="def-name">ecl_null_terminated_base_string(cl_object</strong> <code class="def-code-arguments">s)</code><a class="copiable-link" href='Foreign-Function-Interface.html#index-ecl_005fnull_005fterminated_005fbase_005fstring_0028cl_005fobject'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Tries to coerce a string to a simple base string suitable for
|
|||
|
<code class="code">ecl_base_string_pointer_safe</code>. This function may cons data.
|
|||
|
</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<hr>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="subsection-level-extent" id="Higher-level-interfaces">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Foreign-Function-Interface.html#SFFI-Reference" accesskey="n" rel="next">SFFI Reference</a>, Previous: <a href="Foreign-Function-Interface.html#Foreign-objects" accesskey="p" rel="prev">Foreign objects</a>, Up: <a href="Foreign-Function-Interface.html#Foreign-Function-Interface" accesskey="u" rel="up">Foreign Function Interface</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsection" id="Higher-level-interfaces-1">3.3.4 Higher level interfaces</h4>
|
|||
|
<p>Up to now we have only discussed vague ideas about how a FFI works, but you are probably more
|
|||
|
interested on how to actually code all these things in lisp. You have here three
|
|||
|
possibilities:
|
|||
|
</p>
|
|||
|
<ul class="itemize mark-bullet">
|
|||
|
<li>ECL supplies a high level interface which is compatible with UFFI up to
|
|||
|
version 1.8 (api for >=v2.0 is provided by cffi-uffi-compat system
|
|||
|
shipped with CFFI). Code designed for UFFI library should run mostly
|
|||
|
unchanged with ECL. Note, that api resides in ffi package, not uffi, to
|
|||
|
prevent conflicts with cffi-uffi-compat. New code shouldn’t use this
|
|||
|
interface preferring <a class="url" href="https://common-lisp.net/project/cffi/">CFFI</a>.
|
|||
|
</li><li>The <a class="url" href="https://common-lisp.net/project/cffi/">CFFI</a> library features a
|
|||
|
complete backend for ECL. This method of interfacing with the foreign
|
|||
|
libraries is preferred over using UFFI.
|
|||
|
</li><li>ECL’s own low level interface. Only to be used if ECL is your deployment
|
|||
|
platform. It features some powerful constructs that allow you to mix
|
|||
|
arbitrary C and lisp code.
|
|||
|
</li></ul>
|
|||
|
|
|||
|
<p>In the following two subsections we will discuss two practical examples of using the native
|
|||
|
UFFI and the CFFI library.
|
|||
|
</p>
|
|||
|
|
|||
|
<h4 class="subsubheading" id="UFFI-example">UFFI example</h4>
|
|||
|
<a class="index-entry-id" id="index-UFFI-usage"></a>
|
|||
|
|
|||
|
<p>The example below shows how to use UFFI in an application. There are several important
|
|||
|
ingredients:
|
|||
|
</p>
|
|||
|
<ul class="itemize mark-bullet">
|
|||
|
<li>You need to specify the libraries you use and do it at the toplevel, so
|
|||
|
that the compiler may include them at link time.
|
|||
|
</li><li>Every function you will use has to be declared using
|
|||
|
<code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003adef_002dfunction">ffi:def-function</a></code>.
|
|||
|
</li><li>In the cases of headers not used by ECL, a header to include might need
|
|||
|
to be specified using <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003aclines">ffi:clines</a></code>.
|
|||
|
</li></ul>
|
|||
|
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">#|
|
|||
|
Build and load this module with (compile-file "uffi.lsp" :load t)
|
|||
|
|#
|
|||
|
;;
|
|||
|
;; This toplevel statement notifies the compiler that we will
|
|||
|
;; need this shared library at runtime. We do not need this
|
|||
|
;; statement in windows or modern macOS.
|
|||
|
;; The actually needed path to libm might be different on different systems.
|
|||
|
;;
|
|||
|
#-(or ming32 windows darwin)
|
|||
|
(ffi:load-foreign-library "/usr/lib/libm.so")
|
|||
|
;;
|
|||
|
;; With this other statement, we import the C function sin(),
|
|||
|
;; which operates on IEEE doubles.
|
|||
|
;;
|
|||
|
(ffi:def-function ("sin" c-sin) ((arg :double))
|
|||
|
:returning :double)
|
|||
|
;;
|
|||
|
;; We now use this function and compare with the lisp version.
|
|||
|
;;
|
|||
|
(format t "~%Lisp sin:~t~d~%C sin:~t~d~%Difference:~t~d"
|
|||
|
(sin 1.0d0) (c-sin 1.0d0) (- (sin 1.0d0) (c-sin 1.0d0)))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<h4 class="subsubheading" id="CFFI-example">CFFI example</h4>
|
|||
|
<a class="index-entry-id" id="index-CFFI-usage"></a>
|
|||
|
|
|||
|
<p>The <a class="url" href="https://common-lisp.net/project/cffi/">CFFI</a> library is an
|
|||
|
independent project and it is not shipped with ECL. If you wish to use
|
|||
|
it you can go to their homepage, download the code and build it using
|
|||
|
ASDF.
|
|||
|
</p>
|
|||
|
<p>CFFI differs slightly from UFFI in that functions may be used even
|
|||
|
without being declared beforehand.
|
|||
|
</p>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">#|
|
|||
|
Build and load this module with (compile-file "cffi.lsp" :load t)
|
|||
|
|#
|
|||
|
;;
|
|||
|
;; This toplevel statement notifies the compiler that we will
|
|||
|
;; need this shared library at runtime. We do not need this
|
|||
|
;; statement in windows or macOS.
|
|||
|
;;
|
|||
|
#-(or ming32 windows darwin)
|
|||
|
(cffi:load-foreign-library "/usr/lib/libm.so")
|
|||
|
;;
|
|||
|
;; With this other statement, we import the C function sin(),
|
|||
|
;; which operates on IEEE doubles.
|
|||
|
;;
|
|||
|
(cffi:defcfun ("sin" c-sin) :double '(:double))
|
|||
|
;;
|
|||
|
;; We now use this function and compare with the lisp version.
|
|||
|
;;
|
|||
|
(format t "~%Lisp sin:~t~d~%C sin:~t~d~%Difference:~t~d"
|
|||
|
(sin 1.0d0) (c-sin 1.0d0) (- (sin 1.0d0) (c-sin 1.0d0)))
|
|||
|
;;
|
|||
|
;; The following also works: no declaration!
|
|||
|
;;
|
|||
|
(let ((c-cos (cffi:foreign-funcall "cos" :double 1.0d0 :double)))
|
|||
|
(format t "~%Lisp cos:~t~d~%C cos:~t~d~%Difference:~t~d"
|
|||
|
(cos 1.0d0) c-cos (- (cos 1.0d0) c-cos)))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<h4 class="subsubheading" id="SFFI-example-_0028low-level-inlining_0029">SFFI example (low level inlining)</h4>
|
|||
|
<a class="index-entry-id" id="index-SFFI-usage"></a>
|
|||
|
|
|||
|
<p>To compare with the previous pieces of code, we show how the previous programs would be
|
|||
|
written using <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003aclines">ffi:clines</a></code> and <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003ac_002dinline">ffi:c-inline</a></code>.
|
|||
|
</p>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">#|
|
|||
|
Build and load this module with (compile-file "ecl.lsp" :load t)
|
|||
|
|#
|
|||
|
;;
|
|||
|
;; With this other statement, we import the C function sin(), which
|
|||
|
;; operates on IEEE doubles. Notice that we include the C header to
|
|||
|
;; get the full declaration.
|
|||
|
;;
|
|||
|
(defun c-sin (x)
|
|||
|
(ffi:clines "#include <math.h>")
|
|||
|
(ffi:c-inline (x) (:double) :double "sin(#0)" :one-liner t))
|
|||
|
;;
|
|||
|
;; We now use this function and compare with the lisp version.
|
|||
|
;;
|
|||
|
(format t "~%Lisp sin:~t~d~%C sin:~t~d~%Difference:~t~d"
|
|||
|
(sin 1.0d0) (c-sin 1.0d0) (- (sin 1.0d0) (c-sin 1.0d0)))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<hr>
|
|||
|
</div>
|
|||
|
<div class="subsection-level-extent" id="SFFI-Reference">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Foreign-Function-Interface.html#DFFI-Reference" accesskey="n" rel="next">DFFI Reference</a>, Previous: <a href="Foreign-Function-Interface.html#Higher-level-interfaces" accesskey="p" rel="prev">Higher level interfaces</a>, Up: <a href="Foreign-Function-Interface.html#Foreign-Function-Interface" accesskey="u" rel="up">Foreign Function Interface</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsection" id="SFFI-Reference-1">3.3.5 SFFI Reference</h4>
|
|||
|
<a class="index-entry-id" id="index-C_002fC_002b_002b-code-inlining"></a>
|
|||
|
<a class="index-entry-id" id="index-Static-foreign-function-interface"></a>
|
|||
|
|
|||
|
<h4 class="subsubheading" id="Reference">Reference</h4>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aclines"></a><a class="index-entry-id" id="index-ffi_003aclines-1"></a>
|
|||
|
<dl class="first-deffn first-defspec-alias-first-deffn">
|
|||
|
<dt class="deffn defspec-alias-deffn" id="index-ffi_003aclines"><span class="category-def">Special Form: </span><span><strong class="def-name">ffi:clines</strong> <var class="def-var-arguments">c/c++-code*</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aclines'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Insert C declarations and definitions
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">c/c++-code</var></dt>
|
|||
|
<dd><p>One or more strings with C definitions. Not evaluated.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>No value.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>This special form inserts C code from strings passed in the
|
|||
|
<var class="var">arguments</var> directly in the file that results from compiling lisp
|
|||
|
sources. Contrary to <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003ac_002dinline">ffi:c-inline</a></code>, this function may have no
|
|||
|
executable statements, accepts no input value and returns no value.
|
|||
|
</p>
|
|||
|
<p>The main use of <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003aclines">ffi:clines</a></code> is to declare or define C variables
|
|||
|
and functions that are going to be used later in other FFI
|
|||
|
statements. All statements from <var class="var">arguments</var> are grouped at the
|
|||
|
beginning of the produced header file.
|
|||
|
</p>
|
|||
|
<p><code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003aclines">ffi:clines</a></code> is a special form that can only be used in lisp
|
|||
|
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.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-adding-c-toplevel-declarations"></a>
|
|||
|
<p>In this example the <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003aclines">ffi:clines</a></code> statement is required to get
|
|||
|
access to the C function <code class="code">cos</code>:
|
|||
|
</p><div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:clines "#include <math.h>")
|
|||
|
(defun cos (x)
|
|||
|
(ffi:c-inline (x) (:double) :double "cos(#0)" :one-liner t))
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003ac_002dinline"></a><a class="index-entry-id" id="index-ffi_003ac_002dinline-1"></a>
|
|||
|
<dl class="first-deffn first-defspec-alias-first-deffn">
|
|||
|
<dt class="deffn defspec-alias-deffn" id="index-ffi_003ac_002dinline"><span class="category-def">Special Form: </span><span><strong class="def-name">ffi:c-inline</strong> <var class="def-var-arguments">(lisp-values) (arg-c-types) return-type c/c++-code &key (side-effects t) (one-liner nil)</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003ac_002dinline'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Inline C code in a lisp form
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">lisp-values</var></dt>
|
|||
|
<dd><p>One or more lisp expressions. Evaluated.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">arg-c-types</var></dt>
|
|||
|
<dd><p>One or more valid FFI types. Evaluated.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">return-type</var></dt>
|
|||
|
<dd><p>Valid FFI type or <code class="code">(values ffi-type*)</code>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">c/c++-code</var></dt>
|
|||
|
<dd><p>String containing valid C code plus some valid escape forms.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">one-liner</var></dt>
|
|||
|
<dd><p>Boolean indicating, if the expression is a valid R-value. Defaults to
|
|||
|
<code class="code">nil</code>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">side-effects</var></dt>
|
|||
|
<dd><p>Boolean indicating, if the expression causes side effects. Defaults to
|
|||
|
<code class="code">t</code>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>One or more lisp values.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>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.
|
|||
|
</p>
|
|||
|
<p>The first argument <var class="var">lisp-values</var> is a list of lisp forms. These
|
|||
|
forms are going to be evaluated and their lisp values will be
|
|||
|
transformed to the corresponding C types denoted by the elements in the
|
|||
|
list <var class="var">arg-c-types</var>.
|
|||
|
</p>
|
|||
|
<p>The input values are used to create a valid C expression using the
|
|||
|
template in <var class="var">C/C++-code</var>. This is a string of arbitrary size which
|
|||
|
mixes C expressions with two kind of escape forms.
|
|||
|
</p>
|
|||
|
<p>The first kind of escape form are made of a hash and a letter or a
|
|||
|
number, as in: <code class="code">#0</code>, <code class="code">#1</code>, ..., until <code class="code">#z</code>. These codes
|
|||
|
are replaced by the corresponding input values. The second kind of
|
|||
|
escape form has the format <code class="code">@(return [n])</code>, it can be used as
|
|||
|
lvalue in a C expression and it is used to set the n-th output value of
|
|||
|
the <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003ac_002dinline">ffi:c-inline</a></code> form.
|
|||
|
</p>
|
|||
|
<p>When the parameter <var class="var">one-liner</var> is true, then the C template must be
|
|||
|
a simple C statement that outputs a value. In this case the use of
|
|||
|
<code class="code">@(return)</code> is not allowed. When the parameter <var class="var">one-liner</var> is
|
|||
|
false, then the C template may be a more complicated block form, with
|
|||
|
braces, conditionals, loops and spanning multiple lines. In this case
|
|||
|
the output of the form can only be set using <code class="code">@(return)</code>.
|
|||
|
</p>
|
|||
|
<p>Parameter <var class="var">side-effects</var> set to false will indicate, that the
|
|||
|
functions causes no side-effects. This information is used by the
|
|||
|
compiler to optimize the resulting code. If <var class="var">side-effects</var> is set to
|
|||
|
false, but the function may cause the side effects, then results are
|
|||
|
undefined.
|
|||
|
</p>
|
|||
|
<p>Note that the conversion between lisp arguments and FFI types is
|
|||
|
automatic. Note also that <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003ac_002dinline">ffi:c-inline</a></code> cannot be used in
|
|||
|
interpreted or bytecompiled code! Such usage will signal an error.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-inlining-c-code"></a>
|
|||
|
<p>The following example implements the transcendental function SIN using
|
|||
|
the C equivalent:
|
|||
|
</p>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:c-lines "#include <math.h>")
|
|||
|
(defun mysin (x)
|
|||
|
(ffi:c-inline (x) (:double) :double
|
|||
|
"sin(#0)"
|
|||
|
:one-liner t
|
|||
|
:side-effects nil))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<p>This function can also be implemented using the <code class="code">@(return)</code> form
|
|||
|
as follows:
|
|||
|
</p>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="verbatim">(defun mysin (x)
|
|||
|
(ffi:c-inline (x) (:double) :double
|
|||
|
"@(return)=sin(#0);"
|
|||
|
:side-effects nil))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<p>The following example is slightly more complicated as it involves loops
|
|||
|
and two output values:
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-returning-multiple-values"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="verbatim">(defun sample (x)
|
|||
|
(ffi:c-inline (x (+ x 2)) (:int :int) (values :int :int) "{
|
|||
|
int n1 = #0, n2 = #1, out1 = 0, out2 = 1;
|
|||
|
while (n1 <= n2) {
|
|||
|
out1 += n1;
|
|||
|
out2 *= n1;
|
|||
|
n1++;
|
|||
|
}
|
|||
|
@(return 0)= out1;
|
|||
|
@(return 1)= out2;
|
|||
|
}"
|
|||
|
:side-effects nil))
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003ac_002dprogn"></a><a class="index-entry-id" id="index-ffi_003ac_002dprogn-1"></a>
|
|||
|
<dl class="first-deffn first-defspec-alias-first-deffn">
|
|||
|
<dt class="deffn defspec-alias-deffn" id="index-ffi_003ac_002dprogn"><span class="category-def">Special Form: </span><span><strong class="def-name">ffi:c-progn</strong> <var class="def-var-arguments">args &body body</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003ac_002dprogn'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Interleave C statements with the Lisp code
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">args</var></dt>
|
|||
|
<dd><p>Lisp arguments. Evaluated.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>No value.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>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 class="code">cl_object</code>.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-interleaving-c-and-lisp-code"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="verbatim">(lambda (i)
|
|||
|
(let* ((limit i)
|
|||
|
(iterator 0)
|
|||
|
(custom-var (cons 1 2)))
|
|||
|
(declare (:int limit iterator))
|
|||
|
(ffi:c-progn (limit iterator custom-var)
|
|||
|
"cl_object cv = #2;"
|
|||
|
"ecl_print(cv, ECL_T);"
|
|||
|
"for (#1 = 0; #1 < #0; #1++) {"
|
|||
|
(format t "~&Iterator: ~A, I: ~A~%" iterator i)
|
|||
|
"}")))
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adefcallback"></a><a class="index-entry-id" id="index-ffi_003adefcallback-1"></a>
|
|||
|
<dl class="first-deffn first-defspec-alias-first-deffn">
|
|||
|
<dt class="deffn defspec-alias-deffn" id="index-ffi_003adefcallback"><span class="category-def">Special Form: </span><span><strong class="def-name">ffi:defcallback</strong> <var class="def-var-arguments">name ret-type arg-desc &body body</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adefcallback'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>Name of the lisp function.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">ret-type</var></dt>
|
|||
|
<dd><p>Declaration of the return type which function returns.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">arg-desc</var></dt>
|
|||
|
<dd><p>List of pairs <code class="code">(arg-name arg-type)</code>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">body</var></dt>
|
|||
|
<dd><p>Function body.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>Pointer to the defined callback.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>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).
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adefcbody"></a><a class="index-entry-id" id="index-ffi_003adefcbody-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adefcbody"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:defcbody</strong> <var class="def-var-arguments">name arg-types result-type c-expression</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adefcbody'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Define C function under the lisp name
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>Defined function name.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">arg-types</var></dt>
|
|||
|
<dd><p>Argument types of the defined Lisp function.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">result-type</var></dt>
|
|||
|
<dd><p>Result type of the C function (may be <code class="code">(values ...)</code>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>Defined function name.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>The compiler defines a Lisp function named by <var class="var">name</var> whose body
|
|||
|
consists of the C code of the string <var class="var">c-expression</var>. In the
|
|||
|
<var class="var">c-expression</var> one can reference the arguments of the function as
|
|||
|
<code class="code">#0</code>, <code class="code">#1</code>, etc.
|
|||
|
</p>
|
|||
|
<p>The interpreter ignores this form.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adefentry"></a><a class="index-entry-id" id="index-ffi_003adefentry-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adefentry"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:defentry</strong> <var class="def-var-arguments">name arg-types c-name &key no-interrupts</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adefentry'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>Lisp name for the function.
|
|||
|
</p>
|
|||
|
</dd>
|
|||
|
<dt><var class="var">arg-types</var></dt>
|
|||
|
<dd><p>Argument types of the C function.
|
|||
|
</p>
|
|||
|
</dd>
|
|||
|
<dt><var class="var">c-name</var></dt>
|
|||
|
<dd><p>If <var class="var">c-name</var> is a list, then C function result type is declared as
|
|||
|
<code class="code">(car c-name)</code> and its name is <code class="code">(string (cdr c-name))</code>.
|
|||
|
</p>
|
|||
|
<p>If it’s an atom, then the result type is <code class="code">:object</code>, and function
|
|||
|
name is <code class="code">(string c-name)</code>.
|
|||
|
</p>
|
|||
|
</dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>Lisp function <code class="code">name</code>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>The compiler defines a Lisp function named by <var class="var">name</var> whose body
|
|||
|
consists of a calling sequence to the C language function named by
|
|||
|
<var class="var">c-name</var>.
|
|||
|
</p>
|
|||
|
<p>The interpreter ignores this form.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<a class="anchor" id="ext_003awith_002dbackend"></a><a class="index-entry-id" id="index-ext_003awith_002dbackend-1"></a>
|
|||
|
<dl class="first-deffn first-defspec-alias-first-deffn">
|
|||
|
<dt class="deffn defspec-alias-deffn" id="index-ext_003awith_002dbackend"><span class="category-def">Special Form: </span><span><strong class="def-name">ext:with-backend</strong> <var class="def-var-arguments">&key bytecodes c/c++</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ext_003awith_002dbackend'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Use different code depending on the backend.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Depending on whether the bytecodes or C compiler is used, this form will
|
|||
|
emit the code given in the corresponding keyword argument.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-use-different-code-for-c-and-bytecodes-compiler"></a>
|
|||
|
<pre class="verbatim">CL-USER> (defmacro test ()
|
|||
|
'(ext:with-backend :c/c++ "c/c++" :bytecodes "bytecodes"))
|
|||
|
TEST
|
|||
|
CL-USER> (test)
|
|||
|
"bytecodes"
|
|||
|
CL-USER> (funcall (compile nil (lambda () (test))))
|
|||
|
|
|||
|
;;; OPTIMIZE levels: Safety=2, Space=0, Speed=3, Debug=3
|
|||
|
"c/c++"
|
|||
|
|
|||
|
</pre></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adefla"></a><a class="index-entry-id" id="index-ffi_003adefla-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adefla"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:defla</strong> <var class="def-var-arguments">name args &body body</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adefla'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Provide Lisp alternative for interpreted code.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Used to DEFine Lisp Alternative. For the interpreter,
|
|||
|
<code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003adefla">ffi:defla</a></code> is equivalent to <code class="code">defun</code>, but the compiler
|
|||
|
ignores this form.
|
|||
|
</p></dd></dl>
|
|||
|
<hr>
|
|||
|
</div>
|
|||
|
<div class="subsection-level-extent" id="DFFI-Reference">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Foreign-Function-Interface.html#UFFI-Reference" accesskey="n" rel="next">UFFI Reference</a>, Previous: <a href="Foreign-Function-Interface.html#SFFI-Reference" accesskey="p" rel="prev">SFFI Reference</a>, Up: <a href="Foreign-Function-Interface.html#Foreign-Function-Interface" accesskey="u" rel="up">Foreign Function Interface</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsection" id="DFFI-Reference-1">3.3.6 DFFI Reference</h4>
|
|||
|
<a class="index-entry-id" id="index-Dynamic-foreign-function-interface"></a>
|
|||
|
|
|||
|
<a class="index-entry-id" id="index-ffi_003a_002ause_002ddffi_002a"></a>
|
|||
|
<dl class="first-defvr">
|
|||
|
<dt class="defvr" id="index-ffi_003a_002ause_002ddffi_002a-1"><span class="category-def">Variable: </span><span><strong class="def-name">ffi:*use-dffi*</strong><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003a_002ause_002ddffi_002a-1'> ¶</a></span></dt>
|
|||
|
<dd><p>This variable controls whether DFFI is used or not.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<hr>
|
|||
|
</div>
|
|||
|
<div class="subsection-level-extent" id="UFFI-Reference">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Previous: <a href="Foreign-Function-Interface.html#DFFI-Reference" accesskey="p" rel="prev">DFFI Reference</a>, Up: <a href="Foreign-Function-Interface.html#Foreign-Function-Interface" accesskey="u" rel="up">Foreign Function Interface</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsection" id="UFFI-Reference-1">3.3.7 UFFI Reference</h4>
|
|||
|
<a class="index-entry-id" id="index-Universal-foreign-function-interface"></a>
|
|||
|
|
|||
|
|
|||
|
<ul class="mini-toc">
|
|||
|
<li><a href="Foreign-Function-Interface.html#Primitive-Types" accesskey="1">Primitive Types</a></li>
|
|||
|
<li><a href="Foreign-Function-Interface.html#Aggregate-Types" accesskey="2">Aggregate Types</a></li>
|
|||
|
<li><a href="Foreign-Function-Interface.html#Foreign-Objects" accesskey="3">Foreign Objects</a></li>
|
|||
|
<li><a href="Foreign-Function-Interface.html#Foreign-Strings" accesskey="4">Foreign Strings</a></li>
|
|||
|
<li><a href="Foreign-Function-Interface.html#Functions-and-Libraries" accesskey="5">Functions and Libraries</a></li>
|
|||
|
</ul>
|
|||
|
<hr>
|
|||
|
<div class="subsubsection-level-extent" id="Primitive-Types">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Foreign-Function-Interface.html#Aggregate-Types" accesskey="n" rel="next">Aggregate Types</a>, Up: <a href="Foreign-Function-Interface.html#UFFI-Reference" accesskey="u" rel="up">UFFI Reference</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsubsection" id="Primitive-Types-1">3.3.7.1 Primitive Types</h4>
|
|||
|
<a class="index-entry-id" id="index-Foreign-primitive-types"></a>
|
|||
|
|
|||
|
<p>Primitive types have a single value, these include characters, numbers,
|
|||
|
and pointers. They are all symbols in the keyword package.
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-_003achar"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aunsigned_002dchar"></a>
|
|||
|
<a class="index-entry-id" id="index-_003abyte"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aunsigned_002dbyte"></a>
|
|||
|
<a class="index-entry-id" id="index-_003ashort"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aunsigned_002dshort"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aint"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aunsigned_002dint"></a>
|
|||
|
<a class="index-entry-id" id="index-_003along"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aunsigned_002dlong"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aint16_002dt"></a>
|
|||
|
<a class="index-entry-id" id="index-_003auint16_002dt"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aint32_002dt"></a>
|
|||
|
<a class="index-entry-id" id="index-_003auint32_002dt"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aint64_002dt"></a>
|
|||
|
<a class="index-entry-id" id="index-_003auint64_002dt"></a>
|
|||
|
<a class="index-entry-id" id="index-_003afloat"></a>
|
|||
|
<a class="index-entry-id" id="index-_003adouble"></a>
|
|||
|
<a class="index-entry-id" id="index-_003along_002ddouble"></a>
|
|||
|
<a class="index-entry-id" id="index-_003acsfloat"></a>
|
|||
|
<a class="index-entry-id" id="index-_003acdfloat"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aclfloat"></a>
|
|||
|
<a class="index-entry-id" id="index-_003acstring"></a>
|
|||
|
<a class="index-entry-id" id="index-_003avoid"></a>
|
|||
|
<a class="index-entry-id" id="index-_003apointer_002dvoid"></a>
|
|||
|
<a class="index-entry-id" id="index-_003a_002a"></a>
|
|||
|
<a class="index-entry-id" id="index-_003aobject"></a>
|
|||
|
|
|||
|
<a class="index-entry-id" id="index-LONG_002dLONG"></a>
|
|||
|
<a class="index-entry-id" id="index-UINT16_002dT"></a>
|
|||
|
<a class="index-entry-id" id="index-UINT32_002dT"></a>
|
|||
|
<a class="index-entry-id" id="index-UINT64_002dT"></a>
|
|||
|
<a class="index-entry-id" id="index-LONG_002dFLOAT-1"></a>
|
|||
|
<a class="index-entry-id" id="index-COMPLEX_002dFLOAT-1"></a>
|
|||
|
|
|||
|
<dl class="table">
|
|||
|
<dt>‘<samp class="samp">:char</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:unsigned-char</samp>’</dt>
|
|||
|
<dd><p>Signed/unsigned 8-bits. Dereferenced pointer returns a character.
|
|||
|
</p></dd>
|
|||
|
<dt>‘<samp class="samp">:byte</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:unsigned-byte</samp>’</dt>
|
|||
|
<dd><p>Signed/unsigned 8-bits. Dereferenced pointer returns an integer.
|
|||
|
</p></dd>
|
|||
|
<dt>‘<samp class="samp">:short</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:unsigned-short</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:int</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:unsigned-int</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:long</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:unsigned-long</samp>’</dt>
|
|||
|
<dd><p>Standard integer types (16-bit, 32-bit and 32/64-bit).
|
|||
|
</p></dd>
|
|||
|
<dt>‘<samp class="samp">:int16-t</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:uint16-t</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:int32-t</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:uint32-t</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:int64-t</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:uint64-t</samp>’</dt>
|
|||
|
<dd><p>Integer types with guaranteed bitness.
|
|||
|
</p>
|
|||
|
</dd>
|
|||
|
<dt>‘<samp class="samp">:float</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:double</samp>’</dt>
|
|||
|
<dd><p>Floating point numerals (32-bit and 64-bit).
|
|||
|
</p></dd>
|
|||
|
<dt>‘<samp class="samp">:long-double</samp>’</dt>
|
|||
|
<dd><p>Floating point numeral (usually 80-bit, at least 64-bit, exact
|
|||
|
bitness is compiler/architecture/platform dependent).
|
|||
|
</p></dd>
|
|||
|
<dt>‘<samp class="samp">:csfloat</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:cdfloat</samp>’</dt>
|
|||
|
<dt>‘<samp class="samp">:clfloat</samp>’</dt>
|
|||
|
<dd><p>Complex floating point numerals. These types exist only when ECL is
|
|||
|
built with c99complex support.
|
|||
|
</p></dd>
|
|||
|
<dt>‘<samp class="samp">:cstring</samp>’</dt>
|
|||
|
<dd><p>A <code class="code">NULL</code> terminated string used for passing and returning
|
|||
|
characters strings with a C function.
|
|||
|
</p></dd>
|
|||
|
<dt>‘<samp class="samp">:void</samp>’</dt>
|
|||
|
<dd><p>The absence of a value. Used to indicate that a function does not return
|
|||
|
a value.
|
|||
|
</p></dd>
|
|||
|
<dt>‘<samp class="samp">:pointer-void</samp>’</dt>
|
|||
|
<dd><p>Points to a generic object.
|
|||
|
</p></dd>
|
|||
|
<dt>‘<samp class="samp">*</samp>’</dt>
|
|||
|
<dd><p>Used to declare a pointer to an object.
|
|||
|
</p></dd>
|
|||
|
<dt>‘<samp class="samp">:object</samp>’</dt>
|
|||
|
<dd><p>A generic lisp object (i.e. a <code class="code">cl_object</code> in C)
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<h4 class="subsubheading" id="Reference-1">Reference</h4>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adef_002dconstant"></a><a class="index-entry-id" id="index-ffi_003adef_002dconstant-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adef_002dconstant"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:def-constant</strong> <var class="def-var-arguments">name value &key (export nil)</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adef_002dconstant'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Binds a symbol to a constant.
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>A symbol that will be bound to the value.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">value</var></dt>
|
|||
|
<dd><p>An evaluated form that is bound the the name.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">export</var></dt>
|
|||
|
<dd><p>When <code class="code">t</code>, the name is exported from the current package. Defaults
|
|||
|
to <code class="code">nil</code>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>Constant name.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>This is a thin wrapper around <code class="code">defconstant</code>. It evaluates at
|
|||
|
compile-time and optionally exports the symbol from the package.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-defining-constants"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-constant pi2 (* 2 pi))
|
|||
|
(ffi:def-constant exported-pi2 (* 2 pi) :export t)
|
|||
|
</pre></div>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Side Effects</b>
|
|||
|
</p>
|
|||
|
<p>Creates a new special variable.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|

|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adef_002dforeign_002dtype"></a><a class="index-entry-id" id="index-ffi_003adef_002dforeign_002dtype-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adef_002dforeign_002dtype"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:def-foreign-type</strong> <var class="def-var-arguments">name definition</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adef_002dforeign_002dtype'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Defines a new foreign type
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>A symbol naming the new foreign type.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">value</var></dt>
|
|||
|
<dd><p>A form that is not evaluated that defines the new foreign type.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>Foreign type designator (<var class="var">value</var>).
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Defines a new foreign type
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-examples"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-foreign-type my-generic-pointer :pointer-void)
|
|||
|
(ffi:def-foreign-type a-double-float :double-float)
|
|||
|
(ffi:def-foreign-type char-ptr (* :char))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Side effects</b>
|
|||
|
</p>
|
|||
|
<p>Defines a new foreign type.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|

|
|||
|
|
|||
|
<a class="anchor" id="ffi_003anull_002dchar_002dp"></a><a class="index-entry-id" id="index-ffi_003anull_002dchar_002dp-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003anull_002dchar_002dp"><span class="category-def">Function: </span><span><strong class="def-name">ffi:null-char-p</strong> <var class="def-var-arguments">char</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003anull_002dchar_002dp'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Tests a character for NULL value
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">char</var></dt>
|
|||
|
<dd><p>A character or integer.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A boolean flag indicating if <var class="var">char</var> is a NULL value.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>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.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-example"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(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
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|

|
|||
|
|
|||
|
<hr>
|
|||
|
</div>
|
|||
|
<div class="subsubsection-level-extent" id="Aggregate-Types">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Foreign-Function-Interface.html#Foreign-Objects" accesskey="n" rel="next">Foreign Objects</a>, Previous: <a href="Foreign-Function-Interface.html#Primitive-Types" accesskey="p" rel="prev">Primitive Types</a>, Up: <a href="Foreign-Function-Interface.html#UFFI-Reference" accesskey="u" rel="up">UFFI Reference</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsubsection" id="Aggregate-Types-1">3.3.7.2 Aggregate Types</h4>
|
|||
|
<a class="index-entry-id" id="index-Foreign-aggregate-types"></a>
|
|||
|
|
|||
|
<h4 class="subsubheading" id="Overview-3">Overview</h4>
|
|||
|
<p>Aggregate types are comprised of one or more primitive types.
|
|||
|
</p>
|
|||
|
<h4 class="subsubheading" id="Reference-2">Reference</h4>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adef_002denum"></a><a class="index-entry-id" id="index-ffi_003adef_002denum-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adef_002denum"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:def-enum</strong> <var class="def-var-arguments">name fields &key separator-string</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adef_002denum'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Defines a C enumeration
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>A symbol that names the enumeration.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">fields</var></dt>
|
|||
|
<dd><p>A list of field definitions. 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.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A string that governs the creation of constants. The default is "#".
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>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 <code class="code">:int</code>.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-sample-enumerations"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(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
|
|||
|
</pre></div>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Side effects</b>
|
|||
|
</p>
|
|||
|
<p>Creates a <code class="code">:int</code> foreign type, defines constants.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|

|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adef_002dstruct"></a><a class="index-entry-id" id="index-ffi_003adef_002dstruct-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adef_002dstruct"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:def-struct</strong> <var class="def-var-arguments">name &rest fields</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adef_002dstruct'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Defines a C structure
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>A symbol that names the structure.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">fields</var></dt>
|
|||
|
<dd><p>A variable number of field definitions. Each definition is a list
|
|||
|
consisting of a symbol naming the field followed by its foreign type.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>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 class="code">:pointer-self</code>.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-defining-C-structure"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-struct foo (a :unsigned-int)
|
|||
|
(b (* :char))
|
|||
|
(c (:array :int 10))
|
|||
|
(next :pointer-self))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Side effects</b>
|
|||
|
</p>
|
|||
|
<p>Creates a foreign type.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|

|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aget_002dslot_002dvalue"></a><a class="index-entry-id" id="index-ffi_003aget_002dslot_002dvalue-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003aget_002dslot_002dvalue"><span class="category-def">Function: </span><span><strong class="def-name">ffi:get-slot-value</strong> <var class="def-var-arguments">obj type field</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aget_002dslot_002dvalue'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Retrieves a value from a slot of a structure
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">obj</var></dt>
|
|||
|
<dd><p>A pointer to the foreign structure.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">type</var></dt>
|
|||
|
<dd><p>The name of the foreign structure.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">field</var></dt>
|
|||
|
<dd><p>The name of the desired field in the foreign structure.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>The value of the <var class="var">field</var> in the structure <var class="var">obj</var>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Accesses a slot value from a structure. This is generalized and can be
|
|||
|
used with <code class="code">setf</code>.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-manipulating-a-struct-field"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:get-slot-value foo-ptr 'foo-structure 'field-name)
|
|||
|
(setf (ffi:get-slot-value foo-ptr 'foo-structure 'field-name) 10)
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|

|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aget_002dslot_002dpointer"></a><a class="index-entry-id" id="index-ffi_003aget_002dslot_002dpointer-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003aget_002dslot_002dpointer"><span class="category-def">Function: </span><span><strong class="def-name">ffi:get-slot-pointer</strong> <var class="def-var-arguments">obj type field</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aget_002dslot_002dpointer'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Retrieves a pointer from a slot of a structure
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">obj</var></dt>
|
|||
|
<dd><p>A pointer to the foreign structure.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">type</var></dt>
|
|||
|
<dd><p>The name of the foreign structure.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">field</var></dt>
|
|||
|
<dd><p>The name of the desired field in the foreign structure.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>The value of the pointer <var class="var">field</var> in the structure <var class="var">obj</var>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>This is similar to <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003aget_002dslot_002dvalue">ffi:get-slot-value</a></code>. It is used when the
|
|||
|
value of a slot is a pointer type.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-usage"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:get-slot-pointer foo-ptr 'foo-structure 'my-char-ptr)
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|

|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adef_002darray_002dpointer"></a><a class="index-entry-id" id="index-ffi_003adef_002darray_002dpointer-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adef_002darray_002dpointer"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:def-array-pointer</strong> <var class="def-var-arguments">name type</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adef_002darray_002dpointer'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Defines a pointer to an array of <var class="var">type</var>
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>A name of the new foreign type.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">type</var></dt>
|
|||
|
<dd><p>The foreign type of the array elements.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Defines a type that is a pointer to an array of <var class="var">type</var>.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-usage-1"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-array-pointer byte-array-pointer :unsigned-char)
|
|||
|
</pre></div>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Side effects</b>
|
|||
|
</p>
|
|||
|
<p>Defines a new foreign type.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|

|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aderef_002darray"></a><a class="index-entry-id" id="index-ffi_003aderef_002darray-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003aderef_002darray"><span class="category-def">Function: </span><span><strong class="def-name">ffi:deref-array</strong> <var class="def-var-arguments">array type position</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aderef_002darray'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Dereference an array
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">array</var></dt>
|
|||
|
<dd><p>A foreign array.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">type</var></dt>
|
|||
|
<dd><p>The foreign type of the <var class="var">array</var>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">position</var></dt>
|
|||
|
<dd><p>An integer specifying the position to retrieve from the <var class="var">array</var>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>The value stored in the <var class="var">position</var> of the <var class="var">array</var>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Dereferences (retrieves) the value of the foreign array
|
|||
|
element. <code class="code">setf</code>-able.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-retrieving-array-element"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-array-pointer ca :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
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|

|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adef_002dunion"></a><a class="index-entry-id" id="index-ffi_003adef_002dunion-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adef_002dunion"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:def-union</strong> <var class="def-var-arguments">name &rest fields</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adef_002dunion'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Defines a foreign union type
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>A name of the new union type.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">fields</var></dt>
|
|||
|
<dd><p>A list of fields of the union in form <code class="code">(field-name field-type)</code>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Defines a foreign union type.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-union-definition-and-usage"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-union test-union
|
|||
|
(a-char :char)
|
|||
|
(an-int :int))
|
|||
|
|
|||
|
(let ((u (ffi:allocate-foreign-object 'test-union)))
|
|||
|
(setf (ffi:get-slot-value u 'test-union 'an-int) (+ 65 (* 66 256)))
|
|||
|
(prog1
|
|||
|
(ffi:ensure-char-character (ffi:get-slot-value u 'test-union 'a-char))
|
|||
|
(ffi:free-foreign-object u)))
|
|||
|
;; => #\A
|
|||
|
</pre></div>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Side effects</b>
|
|||
|
</p>
|
|||
|
<p>Defines a new foreign type.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<hr>
|
|||
|
</div>
|
|||
|
<div class="subsubsection-level-extent" id="Foreign-Objects">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Foreign-Function-Interface.html#Foreign-Strings" accesskey="n" rel="next">Foreign Strings</a>, Previous: <a href="Foreign-Function-Interface.html#Aggregate-Types" accesskey="p" rel="prev">Aggregate Types</a>, Up: <a href="Foreign-Function-Interface.html#UFFI-Reference" accesskey="u" rel="up">UFFI Reference</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsubsection" id="Foreign-Objects-1">3.3.7.3 Foreign Objects</h4>
|
|||
|
<a class="index-entry-id" id="index-Foreign-objects"></a>
|
|||
|
|
|||
|
<h4 class="subsubheading" id="Overview-4">Overview</h4>
|
|||
|
<p>Objects are entities that can allocated, referred to by pointers, and
|
|||
|
can be freed.
|
|||
|
</p>
|
|||
|
<h4 class="subsubheading" id="Reference-3">Reference</h4>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aallocate_002dforeign_002dobject"></a><a class="index-entry-id" id="index-ffi_003aallocate_002dforeign_002dobject-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003aallocate_002dforeign_002dobject"><span class="category-def">Function: </span><span><strong class="def-name">ffi:allocate-foreign-object</strong> <var class="def-var-arguments">type &optional size</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aallocate_002dforeign_002dobject'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Allocates an instance of a foreign object
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">type</var></dt>
|
|||
|
<dd><p>The type of foreign object to allocate. This parameter is evaluated.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">size</var></dt>
|
|||
|
<dd><p>An optional size parameter that is evaluated. If specified, allocates
|
|||
|
and returns an array of <var class="var">type</var> that is <var class="var">size</var> members long. This
|
|||
|
parameter is evaluated.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A pointer to the foreign object.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Allocates an instance of a foreign object. It returns a pointer to the
|
|||
|
object.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-allocating-structure-object"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-struct ab (a :int) (b :double))
|
|||
|
;; => (:STRUCT (A :INT) (B :DOUBLE))
|
|||
|
(ffi:allocate-foreign-object 'ab)
|
|||
|
;; => #<foreign AB>
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003afree_002dforeign_002dobject"></a><a class="index-entry-id" id="index-ffi_003afree_002dforeign_002dobject-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003afree_002dforeign_002dobject"><span class="category-def">Function: </span><span><strong class="def-name">ffi:free-foreign-object</strong> <var class="def-var-arguments">ptr</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003afree_002dforeign_002dobject'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Frees memory that was allocated for a foreign object
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">ptr</var></dt>
|
|||
|
<dd><p>A pointer to the allocated foreign object to free.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Frees memory that was allocated for a foreign object.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003awith_002dforeign_002dobject"></a><a class="index-entry-id" id="index-ffi_003awith_002dforeign_002dobject-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003awith_002dforeign_002dobject"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:with-foreign-object</strong> <var class="def-var-arguments">(var type) &body body</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003awith_002dforeign_002dobject'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Wraps the allocation, binding and destruction of a foreign object around
|
|||
|
a body of code
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">var</var></dt>
|
|||
|
<dd><p>Variable name to bind.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">type</var></dt>
|
|||
|
<dd><p>Type of foreign object to allocate. This parameter is evaluated.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">body</var></dt>
|
|||
|
<dd><p>Code to be evaluated.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>The result of evaluating the body.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>This function wraps the allocation, binding, and destruction of a
|
|||
|
foreign object around the body of code.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-macro-usage"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(defun gethostname2 ()
|
|||
|
"Returns the hostname"
|
|||
|
(ffi:with-foreign-object (name '(:array :unsigned-char 256))
|
|||
|
(if (zerop (c-gethostname (ffi:char-array-to-pointer name) 256))
|
|||
|
(ffi:convert-from-foreign-string name)
|
|||
|
(error "gethostname() failed."))))
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003asize_002dof_002dforeign_002dtype"></a><a class="index-entry-id" id="index-ffi_003asize_002dof_002dforeign_002dtype-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003asize_002dof_002dforeign_002dtype"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:size-of-foreign-type</strong> <var class="def-var-arguments">ftype</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003asize_002dof_002dforeign_002dtype'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Returns the number of data bytes used by a foreign object type
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">ftype</var></dt>
|
|||
|
<dd><p>A foreign type specifier. This parameter is evaluated.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>Number of data bytes used by a foreign object <var class="var">ftype</var>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Returns the number of data bytes used by a foreign object type. This
|
|||
|
does not include any Lisp storage overhead.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:size-of-foreign-type :unsigned-byte)
|
|||
|
;; => 1
|
|||
|
(ffi:size-of-foreign-type 'my-100-byte-vector-type)
|
|||
|
;; => 100
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003apointer_002daddress"></a><a class="index-entry-id" id="index-ffi_003apointer_002daddress-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003apointer_002daddress"><span class="category-def">Function: </span><span><strong class="def-name">ffi:pointer-address</strong> <var class="def-var-arguments">ptr</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003apointer_002daddress'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Returns the address of a pointer
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">ptr</var></dt>
|
|||
|
<dd><p>A pointer to a foreign object.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>An integer representing the pointer’s address.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Returns the address as an integer of a pointer.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aderef_002dpointer"></a><a class="index-entry-id" id="index-ffi_003aderef_002dpointer-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003aderef_002dpointer"><span class="category-def">Function: </span><span><strong class="def-name">ffi:deref-pointer</strong> <var class="def-var-arguments">ptr ftype</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aderef_002dpointer'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Dereferences a pointer
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">ptr</var></dt>
|
|||
|
<dd><p>Pointer to a foreign object.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">ftype</var></dt>
|
|||
|
<dd><p>Foreign type of the object being pointed to.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>The value of the object where the pointer points.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Returns the object to which a pointer points. <code class="code">setf</code>-able.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Notes</b>
|
|||
|
</p>
|
|||
|
<p>Casting of the pointer may be performed with
|
|||
|
<code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003awith_002dcast_002dpointer">ffi:with-cast-pointer</a></code> together with
|
|||
|
<code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003aderef_002dpointer">ffi:deref-pointer</a></code>/<code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003aderef_002darray">ffi:deref-array</a></code>.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-1"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(let ((intp (ffi:allocate-foreign-object :int)))
|
|||
|
(setf (ffi:deref-pointer intp :int) 10)
|
|||
|
(prog1
|
|||
|
(ffi:deref-pointer intp :int)
|
|||
|
(ffi:free-foreign-object intp)))
|
|||
|
;; => 10
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aensure_002dchar_002dcharacter"></a><a class="index-entry-id" id="index-ffi_003aensure_002dchar_002dcharacter-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003aensure_002dchar_002dcharacter"><span class="category-def">Function: </span><span><strong class="def-name">ffi:ensure-char-character</strong> <var class="def-var-arguments">object</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aensure_002dchar_002dcharacter'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Ensures that a dereferenced <code class="code">:char</code> pointer is a character
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">object</var></dt>
|
|||
|
<dd><p>Either a character or a integer specifying a character code.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A character.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Ensures that an objects obtained by dereferencing <code class="code">:char</code> and
|
|||
|
<code class="code">:unsigned-char</code> pointers is a lisp character.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-2"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(let ((fs (ffi:convert-to-foreign-string "a")))
|
|||
|
(prog1
|
|||
|
(ffi:ensure-char-character (ffi:deref-pointer fs :char))
|
|||
|
(ffi:free-foreign-object fs)))
|
|||
|
;; => #\a
|
|||
|
</pre></div>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Exceptional Situations</b>
|
|||
|
</p>
|
|||
|
<p>Depending upon the implementation and what UFFI expects, this macro may
|
|||
|
signal an error if the object is not a character or integer.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aensure_002dchar_002dinteger"></a><a class="index-entry-id" id="index-ffi_003aensure_002dchar_002dinteger-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003aensure_002dchar_002dinteger"><span class="category-def">Function: </span><span><strong class="def-name">ffi:ensure-char-integer</strong> <var class="def-var-arguments">object</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aensure_002dchar_002dinteger'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Ensures that a dereferenced <code class="code">:char</code> pointer is an integer
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">object</var></dt>
|
|||
|
<dd><p>Either a character or a integer specifying a character code.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>An integer.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Ensures that an objects obtained by dereferencing <code class="code">:char</code> and
|
|||
|
<code class="code">:unsigned-char</code> pointers is a lisp integer.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-3"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(let ((fs (ffi:convert-to-foreign-string "a")))
|
|||
|
(prog1
|
|||
|
(ffi:ensure-char-integer (ffi:deref-pointer fs :char))
|
|||
|
(ffi:free-foreign-object fs)))
|
|||
|
;; => 96
|
|||
|
</pre></div>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Exceptional Situations</b>
|
|||
|
</p>
|
|||
|
<p>Depending upon the implementation and what UFFI expects, this macro may
|
|||
|
signal an error if the object is not a character or integer.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003amake_002dnull_002dpointer"></a><a class="index-entry-id" id="index-ffi_003amake_002dnull_002dpointer-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003amake_002dnull_002dpointer"><span class="category-def">Function: </span><span><strong class="def-name">ffi:make-null-pointer</strong> <var class="def-var-arguments">ftype</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003amake_002dnull_002dpointer'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Create a NULL pointer of a specified type
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">ftype</var></dt>
|
|||
|
<dd><p>A type of object to which the pointer refers.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>The NULL pointer of type <var class="var">ftype</var>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003anull_002dpointer_002dp"></a><a class="index-entry-id" id="index-ffi_003anull_002dpointer_002dp-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003anull_002dpointer_002dp"><span class="category-def">Function: </span><span><strong class="def-name">ffi:null-pointer-p</strong> <var class="def-var-arguments">ptr</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003anull_002dpointer_002dp'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Tests a pointer for NULL value
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">ptr</var></dt>
|
|||
|
<dd><p>A foreign object pointer.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>The boolean flag.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003a_002bnull_002dcstring_002dpointer_002b"></a><a class="index-entry-id" id="index-ffi_003a_002bnull_002dcstring_002dpointer_002b"></a>
|
|||
|
<dl class="first-defvr">
|
|||
|
<dt class="defvr" id="index-ffi_003a_002bnull_002dcstring_002dpointer_002b-1"><span class="category-def">Variable: </span><span><strong class="def-name">ffi:+null-cstring-pointer+</strong><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003a_002bnull_002dcstring_002dpointer_002b-1'> ¶</a></span></dt>
|
|||
|
<dd><p>A NULL cstring pointer. This can be used for testing if a cstring
|
|||
|
returned by a function is NULL.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003awith_002dcast_002dpointer"></a><a class="index-entry-id" id="index-ffi_003awith_002dcast_002dpointer-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003awith_002dcast_002dpointer"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:with-cast-pointer</strong> <var class="def-var-arguments">(var ptr ftype) &body body</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003awith_002dcast_002dpointer'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Wraps a body of code with a pointer cast to a new type
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">var</var></dt>
|
|||
|
<dd><p>Symbol which will be bound to the casted object.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">ptr</var></dt>
|
|||
|
<dd><p>Pointer to a foreign object.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">ftype</var></dt>
|
|||
|
<dd><p>A foreign type of the object being pointed to.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>The value of the object where the pointer points.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Executes <var class="var">body</var> with <var class="var">ptr</var> cast to be a pointer to type
|
|||
|
<var class="var">ftype</var>. <var class="var">var</var> will be bound to this value during the
|
|||
|
execution of <var class="var">body</var>.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-4"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:with-foreign-object (size :int)
|
|||
|
;; FOO is a foreign function returning a :POINTER-VOID
|
|||
|
(let ((memory (foo size)))
|
|||
|
(when (mumble)
|
|||
|
;; at this point we know for some reason that MEMORY points
|
|||
|
;; to an array of unsigned bytes
|
|||
|
(ffi:with-cast-pointer (memory :unsigned-byte)
|
|||
|
(dotimes (i (deref-pointer size :int))
|
|||
|
(do-something-with
|
|||
|
(ffi:deref-array memory '(:array :unsigned-byte) i)))))))
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adef_002dforeign_002dvar"></a><a class="index-entry-id" id="index-ffi_003adef_002dforeign_002dvar-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adef_002dforeign_002dvar"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:def-foreign-var</strong> <var class="def-var-arguments">name type module</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adef_002dforeign_002dvar'> ¶</a></span></dt>
|
|||
|
<dd>
|
|||
|
<p>Defines a symbol macro to access a variable in foreign code
|
|||
|
</p>
|
|||
|
<dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>A string or list specifying the symbol macro’s name. If it is a
|
|||
|
string, that names the foreign variable. A Lisp name is created by
|
|||
|
translating <code class="code">#\_</code> to <code class="code">#\-</code> and by converting to upper-case.
|
|||
|
</p>
|
|||
|
<p>If it is a list, the first item is a string specifying the foreign
|
|||
|
variable name and the second it is a symbol stating the Lisp name.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">type</var></dt>
|
|||
|
<dd><p>A foreign type of the foreign variable.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">module</var></dt>
|
|||
|
<dd><p>Either a string specifying the module (or library) the foreign
|
|||
|
variable resides in, <code class="code">:default</code> if no module needs to be loaded
|
|||
|
or <code class="code">nil</code> to use SFFI.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Defines a symbol macro which can be used to access (get and set) the
|
|||
|
value of a variable in foreign code.
|
|||
|
</p>
|
|||
|
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-places-in-foreign-world"></a>
|
|||
|
|
|||
|
<p>C code defining foreign structure, standalone integer and the accessor:
|
|||
|
</p><div class="example">
|
|||
|
<pre class="verbatim">int baz = 3;
|
|||
|
|
|||
|
typedef struct {
|
|||
|
int x;
|
|||
|
double y;
|
|||
|
} foo_struct;
|
|||
|
|
|||
|
foo_struct the_struct = { 42, 3.2 };
|
|||
|
|
|||
|
int foo () {
|
|||
|
return baz;
|
|||
|
}
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<p>Lisp code defining C structure, function and a variable:
|
|||
|
</p><div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-struct foo-struct
|
|||
|
(x :int)
|
|||
|
(y :double))
|
|||
|
|
|||
|
(ffi:def-function ("foo" foo) ()
|
|||
|
:returning :int
|
|||
|
:module "foo")
|
|||
|
|
|||
|
(ffi:def-foreign-var ("baz" *baz*) :int "foo")
|
|||
|
(ffi:def-foreign-var ("the_struct" *the-struct*) foo-struct "foo")
|
|||
|
|
|||
|
*baz* ;; => 3
|
|||
|
(incf *baz*) ;; => 4
|
|||
|
(foo) ;; => 4
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<hr>
|
|||
|
</div>
|
|||
|
<div class="subsubsection-level-extent" id="Foreign-Strings">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Foreign-Function-Interface.html#Functions-and-Libraries" accesskey="n" rel="next">Functions and Libraries</a>, Previous: <a href="Foreign-Function-Interface.html#Foreign-Objects" accesskey="p" rel="prev">Foreign Objects</a>, Up: <a href="Foreign-Function-Interface.html#UFFI-Reference" accesskey="u" rel="up">UFFI Reference</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsubsection" id="Foreign-Strings-1">3.3.7.4 Foreign Strings</h4>
|
|||
|
<a class="index-entry-id" id="index-Foreign-strings"></a>
|
|||
|
|
|||
|
<h4 class="subsubheading" id="Overview-5">Overview</h4>
|
|||
|
<a class="index-entry-id" id="index-cstring-and-foreign-string-differences"></a>
|
|||
|
|
|||
|
<p>UFFI has functions to two types of C-compatible strings: cstrings and
|
|||
|
foreign strings. cstrings are used only as parameters to and from
|
|||
|
functions. In some implementations a cstring is not a foreign type but
|
|||
|
rather the Lisp string itself. On other platforms a cstring is a newly
|
|||
|
allocated foreign vector for storing characters. The following is an
|
|||
|
example of using cstrings to both send and return a value.
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-cstring-used-to-send-and-return-a-value"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-function ("getenv" c-getenv)
|
|||
|
((name :cstring))
|
|||
|
:returning :cstring)
|
|||
|
|
|||
|
(defun my-getenv (key)
|
|||
|
"Returns an environment variable, or NIL if it does not exist"
|
|||
|
(check-type key string)
|
|||
|
(ffi:with-cstring (key-native key)
|
|||
|
(ffi:convert-from-cstring (c-getenv key-native))))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<p>In contrast, foreign strings are always a foreign vector of characters
|
|||
|
which have memory allocated. Thus, if you need to allocate memory to
|
|||
|
hold the return value of a string, you must use a foreign string and not
|
|||
|
a cstring. The following is an example of using a foreign string for a
|
|||
|
return value.
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-foreign-string-used-to-send-and-return-a-value"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-function ("gethostname" c-gethostname)
|
|||
|
((name (* :unsigned-char))
|
|||
|
(len :int))
|
|||
|
:returning :int)
|
|||
|
|
|||
|
(defun gethostname ()
|
|||
|
"Returns the hostname"
|
|||
|
(let* ((name (ffi:allocate-foreign-string 256))
|
|||
|
(result-code (c-gethostname name 256))
|
|||
|
(hostname (when (zerop result-code)
|
|||
|
(ffi:convert-from-foreign-string name))))
|
|||
|
;; UFFI does not yet provide a universal way to free
|
|||
|
;; memory allocated by C's malloc. At this point, a program
|
|||
|
;; needs to call C's free function to free such memory.
|
|||
|
(unless (zerop result-code)
|
|||
|
(error "gethostname() failed."))))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<p>Foreign functions that return pointers to freshly allocated strings
|
|||
|
should in general not return cstrings, but foreign strings. (There is
|
|||
|
no portable way to release such cstrings from Lisp.) The following is
|
|||
|
an example of handling such a function.
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-Conversion-between-foreign-string-and-cstring"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-function ("readline" c-readline)
|
|||
|
((prompt :cstring))
|
|||
|
:returning (* :char))
|
|||
|
|
|||
|
(defun readline (prompt)
|
|||
|
"Reads a string from console with line-editing."
|
|||
|
(ffi:with-cstring (c-prompt prompt)
|
|||
|
(let* ((c-str (c-readline c-prompt))
|
|||
|
(str (ffi:convert-from-foreign-string c-str)))
|
|||
|
(ffi:free-foreign-object c-str)
|
|||
|
str)))
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<h4 class="subsubheading" id="Reference-4">Reference</h4>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aconvert_002dfrom_002dcstring"></a><a class="index-entry-id" id="index-ffi_003aconvert_002dfrom_002dcstring-2"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003aconvert_002dfrom_002dcstring"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:convert-from-cstring</strong> <var class="def-var-arguments">object</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aconvert_002dfrom_002dcstring'> ¶</a></span></dt>
|
|||
|
<dd><p>Converts a <code class="code">cstring</code> to a Lisp string
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">object</var></dt>
|
|||
|
<dd><p>A <code class="code">cstring</code>
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A Lisp string
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Converts a Lisp string to a cstring. This is most often used when
|
|||
|
processing the results of a foreign function that returns a cstring.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aconvert_002dto_002dcstring"></a><a class="index-entry-id" id="index-ffi_003aconvert_002dto_002dcstring-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003aconvert_002dto_002dcstring"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:convert-to-cstring</strong> <var class="def-var-arguments">object</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aconvert_002dto_002dcstring'> ¶</a></span></dt>
|
|||
|
<dd><p>Converts a Lisp string to a <code class="code">cstring</code>
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">object</var></dt>
|
|||
|
<dd><p>A Lisp string
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A <code class="code">cstring</code>
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Converts a Lisp string to a <code class="code">cstring</code>. The <code class="code">cstring</code> should
|
|||
|
be freed with <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003afree_002dcstring">ffi:free-cstring</a></code>.
|
|||
|
</p>
|
|||
|
<p><b class="b">Side Effects</b>
|
|||
|
</p>
|
|||
|
<p>This function allocates memory.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003afree_002dcstring"></a><a class="index-entry-id" id="index-ffi_003afree_002dcstring"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003aconvert_002dfrom_002dcstring-1"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:convert-from-cstring</strong> <var class="def-var-arguments">cstring</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aconvert_002dfrom_002dcstring-1'> ¶</a></span></dt>
|
|||
|
<dd><p>Free memory used by <var class="var">cstring</var>
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">cstring</var></dt>
|
|||
|
<dd><p><code class="code">cstring</code> to be freed.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Frees any memory possibly allocated by <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003aconvert_002dto_002dcstring">ffi:convert-to-cstring</a></code>.
|
|||
|
On ECL, a <code class="code">cstring</code> is just the Lisp string itself.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003awith_002dcstring"></a><a class="index-entry-id" id="index-ffi_003awith_002dcstring-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003awith_002dcstring"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:with-cstring</strong> <var class="def-var-arguments">(cstring string) &body body</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003awith_002dcstring'> ¶</a></span></dt>
|
|||
|
<dd><p>Binds a newly created <code class="code">cstring</code>
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">cstring</var></dt>
|
|||
|
<dd><p>A symbol naming the <code class="code">cstring</code> to be created.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">string</var></dt>
|
|||
|
<dd><p>A Lisp string that will be translated to a <code class="code">cstring</code>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">body</var></dt>
|
|||
|
<dd><p>The body of where the <var class="var">cstring</var> will be bound.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>Result of evaluating the <var class="var">body</var>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Binds a symbol to a <code class="code">cstring</code> created from conversion of a
|
|||
|
<var class="var">string</var>. Automatically frees the <var class="var">cstring</var>.
|
|||
|
</p>
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-with_002dcstring"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-function ("getenv" c-getenv)
|
|||
|
((name :cstring))
|
|||
|
:returning :cstring)
|
|||
|
|
|||
|
(defun getenv (key)
|
|||
|
"Returns an environment variable, or NIL if it does not exist"
|
|||
|
(check-type key string)
|
|||
|
(ffi:with-cstring (key-cstring key)
|
|||
|
(ffi:convert-from-cstring (c-getenv key-cstring))))
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003awith_002dcstrings"></a><a class="index-entry-id" id="index-ffi_003awith_002dcstrings-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003awith_002dcstrings"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:with-cstrings</strong> <var class="def-var-arguments">bindings &body body</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003awith_002dcstrings'> ¶</a></span></dt>
|
|||
|
<dd><p>Binds a newly created <code class="code">cstrings</code>
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">bindings</var></dt>
|
|||
|
<dd><p>List of pairs <var class="var">(cstring string)</var>, where <var class="var">cstring</var> is a name
|
|||
|
for a <code class="code">cstring</code> translated from Lisp string <var class="var">string</var>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">body</var></dt>
|
|||
|
<dd><p>The body of where the <var class="var">bindings</var> will be bound.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>Result of evaluating the <var class="var">body</var>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Binds a symbols to a <code class="code">cstring</code>s created from conversion of a
|
|||
|
<var class="var">string</var>s. Automatically frees the <var class="var">cstring</var>s. This macro works
|
|||
|
similar to <code class="code">let*</code>. Based on <code class="code">with-cstring</code>.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aconvert_002dfrom_002dforeign_002dstring"></a><a class="index-entry-id" id="index-ffi_003aconvert_002dfrom_002dforeign_002dstring-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003aconvert_002dfrom_002dforeign_002dstring"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:convert-from-foreign-string</strong> <var class="def-var-arguments">foreign-string &key length (null-terminated-p t)</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aconvert_002dfrom_002dforeign_002dstring'> ¶</a></span></dt>
|
|||
|
<dd><p>Converts a foreign string into a Lisp string
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">foreign-string</var></dt>
|
|||
|
<dd><p>A foreign string.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">length</var></dt>
|
|||
|
<dd><p>The length of the foreign string to convert. The default is the length
|
|||
|
of the string until a NULL character is reached.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">null-terminated-p</var></dt>
|
|||
|
<dd><p>A boolean flag with a default value of <code class="code">t</code>. When true, the string is
|
|||
|
converted until the first NULL character is reached.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A Lisp string.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Returns a Lisp string from a foreign string. Can translate ASCII and
|
|||
|
binary strings.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aconvert_002dto_002dforeign_002dstring"></a><a class="index-entry-id" id="index-ffi_003aconvert_002dto_002dforeign_002dstring-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003aconvert_002dto_002dforeign_002dstring"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:convert-to-foreign-string</strong> <var class="def-var-arguments">string</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aconvert_002dto_002dforeign_002dstring'> ¶</a></span></dt>
|
|||
|
<dd><p>Converts a Lisp string to a foreign string
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">string</var></dt>
|
|||
|
<dd><p>A Lisp string.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A foreign string.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Converts a Lisp string to a foreign string. Memory should be freed with
|
|||
|
<code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003afree_002dforeign_002dobject">ffi:free-foreign-object</a></code>.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aallocate_002dforeign_002dstring"></a><a class="index-entry-id" id="index-ffi_003aallocate_002dforeign_002dstring-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003aallocate_002dforeign_002dstring"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:allocate-foreign-string</strong> <var class="def-var-arguments">size &key unsigned</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aallocate_002dforeign_002dstring'> ¶</a></span></dt>
|
|||
|
<dd><p>Allocates space for a foreign string
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">size</var></dt>
|
|||
|
<dd><p>The size of the space to be allocated in bytes.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">unsigned</var></dt>
|
|||
|
<dd><p>A boolean flag with a default value of <code class="code">t</code>. When true, marks the pointer
|
|||
|
as an <code class="code">:unsigned-char</code>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A foreign string which has undefined contents.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Allocates space for a foreign string. Memory should be freed with
|
|||
|
<code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003afree_002dforeign_002dobject">ffi:free-foreign-object</a></code>.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003awith_002dforeign_002dstring"></a><a class="index-entry-id" id="index-ffi_003awith_002dforeign_002dstring-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003awith_002dforeign_002dstring"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:with-foreign-string</strong> <var class="def-var-arguments">(foreign-string string) &body body</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003awith_002dforeign_002dstring'> ¶</a></span></dt>
|
|||
|
<dd><p>Binds a newly allocated <code class="code">foreign-string</code>
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">foreign-string</var></dt>
|
|||
|
<dd><p>A symbol naming the <code class="code">foreign string</code> to be created.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">string</var></dt>
|
|||
|
<dd><p>A Lisp string that will be translated to a <code class="code">foreign string</code>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">body</var></dt>
|
|||
|
<dd><p>The body of where the <var class="var">foreign-string</var> will be bound.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>Result of evaluating the <var class="var">body</var>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Binds a symbol to a <code class="code">foreign-string</code> created from conversion of a
|
|||
|
<var class="var">string</var>. Automatically deallocates the <var class="var">foreign-string</var>.
|
|||
|
</p>
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003awith_002dforeign_002dstrings"></a><a class="index-entry-id" id="index-ffi_003awith_002dforeign_002dstrings-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003awith_002dforeign_002dstrings"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:with-foreign-strings</strong> <var class="def-var-arguments">bindings &body body</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003awith_002dforeign_002dstrings'> ¶</a></span></dt>
|
|||
|
<dd><p>Binds a newly created <code class="code">foreign string</code>
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">bindings</var></dt>
|
|||
|
<dd><p>List of pairs <var class="var">(foreign-string string)</var>, where <var class="var">foreign-string</var>
|
|||
|
is a name for a <code class="code">foreign string</code> translated from Lisp string
|
|||
|
<var class="var">string</var>.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">body</var></dt>
|
|||
|
<dd><p>The body of where the <var class="var">bindings</var> will be bound.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>Result of evaluating the <var class="var">body</var>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Binds a symbols to a <code class="code">foreign-string</code>s created from conversion of a
|
|||
|
<var class="var">string</var>s. Automatically frees the <var class="var">foreign-string</var>s. This macro
|
|||
|
works similar to <code class="code">let*</code>. Based on <code class="code"><a class="ref" href="Foreign-Function-Interface.html#ffi_003awith_002dforeign_002dstring">ffi:with-foreign-string</a></code>.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<hr>
|
|||
|
</div>
|
|||
|
<div class="subsubsection-level-extent" id="Functions-and-Libraries">
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Previous: <a href="Foreign-Function-Interface.html#Foreign-Strings" accesskey="p" rel="prev">Foreign Strings</a>, Up: <a href="Foreign-Function-Interface.html#UFFI-Reference" accesskey="u" rel="up">UFFI Reference</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
<h4 class="subsubsection" id="Functions-and-Libraries-1">3.3.7.5 Functions and Libraries</h4>
|
|||
|
<a class="index-entry-id" id="index-Foreign-functions-and-libraries"></a>
|
|||
|
|
|||
|
<h4 class="subsubheading" id="Reference-5">Reference</h4>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003adef_002dfunction"></a><a class="index-entry-id" id="index-ffi_003adef_002dfunction-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003adef_002dfunction"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:def-function</strong> <var class="def-var-arguments">name args &key module (returning :void) (call :cdecl)</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003adef_002dfunction'> ¶</a></span></dt>
|
|||
|
<dd><dl class="table">
|
|||
|
<dt><var class="var">name</var></dt>
|
|||
|
<dd><p>A string or list specifying the function name. If it is a string, that
|
|||
|
names the foreign function. A Lisp name is created by translating
|
|||
|
<code class="code">#\_</code> to <code class="code">#\-</code> and by converting to upper-case in
|
|||
|
case-insensitive Lisp implementations. If it is a list, the first item
|
|||
|
is a string specifying the foreign function name and the second it is a
|
|||
|
symbol stating the Lisp name.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">args</var></dt>
|
|||
|
<dd><p>A list of argument declarations. If <code class="code">nil</code>, indicates that the function
|
|||
|
does not take any arguments.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">module</var></dt>
|
|||
|
<dd><p>Either a string specifying which module (or library) that the foreign
|
|||
|
function resides, <code class="code">:default</code> if no module needs to be loaded or
|
|||
|
<code class="code">nil</code> to use SFFI.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">call</var></dt>
|
|||
|
<dd><p>Function calling convention. May be one of <code class="code">:default</code>, <code class="code">:cdecl</code>,
|
|||
|
<code class="code">:sysv</code>, <code class="code">:stdcall</code>, <code class="code">:win64</code> and
|
|||
|
<code class="code">:unix64</code>.
|
|||
|
</p>
|
|||
|
<p>This argument is used only when we’re using the dynamic function
|
|||
|
interface. If ECL is built without the DFFI support, then it uses SFFI
|
|||
|
the <var class="var">call</var> argument is ignored.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returning</var></dt>
|
|||
|
<dd><p>A declaration specifying the result type of the foreign function.
|
|||
|
<code class="code">:void</code> indicates that the function does not return any value.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Declares a foreign function.
|
|||
|
</p>
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-5"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:def-function "gethostname"
|
|||
|
((name (* :unsigned-char))
|
|||
|
(len :int))
|
|||
|
:returning :int)
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003aload_002dforeign_002dlibrary"></a><a class="index-entry-id" id="index-ffi_003aload_002dforeign_002dlibrary-1"></a>
|
|||
|
<dl class="first-deffn first-defmac-alias-first-deffn">
|
|||
|
<dt class="deffn defmac-alias-deffn" id="index-ffi_003aload_002dforeign_002dlibrary"><span class="category-def">Macro: </span><span><strong class="def-name">ffi:load-foreign-library</strong> <var class="def-var-arguments">filename &key module supporting-libraries force-load system-library</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003aload_002dforeign_002dlibrary'> ¶</a></span></dt>
|
|||
|
<dd><dl class="table">
|
|||
|
<dt><var class="var">filename</var></dt>
|
|||
|
<dd><p>A string or pathname specifying the library location in the filesystem.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">module</var></dt>
|
|||
|
<dd><p><strong class="strong">IGNORED</strong> A string designating the name of the module to apply to
|
|||
|
functions in this library.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">supporting-libraries</var></dt>
|
|||
|
<dd><p><strong class="strong">IGNORED</strong> A list of strings naming the libraries required to link
|
|||
|
the foreign library.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">force-load</var></dt>
|
|||
|
<dd><p><strong class="strong">IGNORED</strong> Forces the loading of the library if it has been
|
|||
|
previously loaded.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">system-library</var></dt>
|
|||
|
<dd><p>Denotes if the loaded library is a system library (accessible with the
|
|||
|
correct linker flags). If <code class="code">t</code>, then SFFI is used and the linking is
|
|||
|
performed after compilation of the module. Otherwise (default) both SFFI
|
|||
|
and DFFI are used, but SFFI only during the compilation.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A generalized boolean <em class="emph">true</em> if the library was able to be loaded
|
|||
|
successfully or if the library has been previously loaded, otherwise
|
|||
|
<code class="code">nil</code>.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Loads a foreign library. Ensures that a library is only loaded once
|
|||
|
during a session.
|
|||
|
</p>
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-6"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:load-foreign-library #p"/usr/lib/libmagic.so.1")
|
|||
|
;; => #<codeblock "/usr/lib/libmagic.so">
|
|||
|
</pre></div>
|
|||
|
|
|||
|
<p><b class="b">Side Effects</b>
|
|||
|
</p>
|
|||
|
<p>Loads the foreign code into the Lisp system.
|
|||
|
</p>
|
|||
|
<p><b class="b">Affected by</b>
|
|||
|
</p>
|
|||
|
<p>Ability to load the file.
|
|||
|
</p></dd></dl>
|
|||
|
|
|||
|
<a class="anchor" id="ffi_003afind_002dforeign_002dlibrary"></a><a class="index-entry-id" id="index-ffi_003afind_002dforeign_002dlibrary-1"></a>
|
|||
|
<dl class="first-deffn first-defun-alias-first-deffn">
|
|||
|
<dt class="deffn defun-alias-deffn" id="index-ffi_003afind_002dforeign_002dlibrary"><span class="category-def">Function: </span><span><strong class="def-name">ffi:find-foreign-library</strong> <var class="def-var-arguments">names directories &key drive-letters types</var><a class="copiable-link" href='Foreign-Function-Interface.html#index-ffi_003afind_002dforeign_002dlibrary'> ¶</a></span></dt>
|
|||
|
<dd><p>Finds a foreign library file
|
|||
|
</p><dl class="table">
|
|||
|
<dt><var class="var">names</var></dt>
|
|||
|
<dd><p>A string or list of strings containing the base name of the library
|
|||
|
file.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">directories</var></dt>
|
|||
|
<dd><p>A string or list of strings containing the directory the library file.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">drive-letters</var></dt>
|
|||
|
<dd><p>A string or list of strings containing the drive letters for the library
|
|||
|
file.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">types</var></dt>
|
|||
|
<dd><p>A string or list of strings containing the file type of the library
|
|||
|
file. Default is <code class="code">nil</code>. If <code class="code">nil</code>, will use a default type
|
|||
|
based on the currently running implementation.
|
|||
|
</p></dd>
|
|||
|
<dt><var class="var">returns</var></dt>
|
|||
|
<dd><p>A path containing the path to the <em class="emph">first</em> file found, or
|
|||
|
<code class="code">nil</code> if the library file was not found.
|
|||
|
</p></dd>
|
|||
|
</dl>
|
|||
|
|
|||
|
<p><b class="b">Description</b>
|
|||
|
</p>
|
|||
|
<p>Finds a foreign library by searching through a number of possible
|
|||
|
locations. Returns the path of the first found file.
|
|||
|
</p>
|
|||
|
<p><b class="b">Examples</b>
|
|||
|
</p>
|
|||
|
<a class="index-entry-id" id="index-html-7"></a>
|
|||
|
<div class="example lisp">
|
|||
|
<pre class="lisp-preformatted">(ffi:find-foreign-library '("libz" "libmagic")
|
|||
|
'("/usr/local/lib/" "/usr/lib/")
|
|||
|
:types '("so" "dll"))
|
|||
|
;; => #P"/usr/lib/libz.so.1.2.8"
|
|||
|
</pre></div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<hr>
|
|||
|
<div class="nav-panel">
|
|||
|
<p>
|
|||
|
Next: <a href="Native-threads.html#Native-threads" accesskey="n" rel="next">Native threads</a>, Previous: <a href="Operating-System-Interface.html#Operating-System-Interface" accesskey="p" rel="prev">Operating System Interface</a>, Up: <a href="Extensions.html" accesskey="u" rel="up">Extensions</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</body>
|
|||
|
</html>
|