Completely remove CFFI
No meaningful progress to update CFFI to experimental status has been made since CFFI was disabled in SWIG-4.0.0 as the first stage to removal. This commit is the final stage to remove it. See issue #1966 for an attempt at updating CFFI to experimental status. Anyone wishing for SWIG to support CFFI again might want to utilise this work.
This commit is contained in:
parent
7b0f7caaf2
commit
cea25abca5
5 changed files with 0 additions and 2156 deletions
|
|
@ -1,604 +0,0 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>SWIG and Common Lisp</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
<H1><a name="Lisp">29 SWIG and Common Lisp</a></H1>
|
||||
<!-- INDEX -->
|
||||
<div class="sectiontoc">
|
||||
<ul>
|
||||
<li><a href="#Lisp_nn3">Common Foreign Function Interface(CFFI)</a>
|
||||
<ul>
|
||||
<li><a href="#Lisp_nn4">Additional Commandline Options </a>
|
||||
<li><a href="#Lisp_nn5">Generating CFFI bindings</a>
|
||||
<li><a href="#Lisp_nn6">Generating CFFI bindings for C++ code</a>
|
||||
<li><a href="#Lisp_nn7">Inserting user code into generated files</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="#Lisp_nn9">Additional Commandline Options </a>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- INDEX -->
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
Common Lisp is a high-level, all-purpose, object-oriented,
|
||||
dynamic, functional programming language with long history.
|
||||
Common Lisp is used in many fields, ranging from web development to
|
||||
finance, and also common in computer science education.
|
||||
There are more than 9 different implementations of common lisp which
|
||||
are available, all have different foreign function
|
||||
interfaces. SWIG currently supports the
|
||||
Common Foreign Function Interface(CFFI).
|
||||
</p>
|
||||
|
||||
<H2><a name="Lisp_nn3">29.2 Common Foreign Function Interface(CFFI)</a></H2>
|
||||
|
||||
|
||||
<p>
|
||||
CFFI, the Common Foreign Function Interface, is a portable foreign
|
||||
function interface for ANSI Common Lisp systems.
|
||||
CFFI requires only a small set of
|
||||
low-level functionality from the Lisp implementation, such as
|
||||
calling a foreign function by name, allocating foreign memory,
|
||||
and dereferencing pointers.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To run the cffi module of SWIG requires very little effort, you
|
||||
just need to run:
|
||||
</p>
|
||||
<div class="code"><pre>
|
||||
swig -cffi -module <i>module-name</i> <i>file-name</i>
|
||||
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
But a better was of using all the power of SWIG is to write SWIG
|
||||
interface files. Below we will explain how to write interface
|
||||
files and the various things which you can do with them.
|
||||
</p>
|
||||
|
||||
<H3><a name="Lisp_nn4">29.2.1 Additional Commandline Options </a></H3>
|
||||
|
||||
|
||||
<table summary="CFFI specific options">
|
||||
<tr>
|
||||
<th> CFFI specific options</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>-generate-typedef</td>
|
||||
<td>If this option is given then defctype will be used to generate<br/>
|
||||
shortcuts according to the typedefs in the input.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>-[no]cwrap</td>
|
||||
<td>Turn on or turn off generation of an intermediate C file when<br/>
|
||||
creating a C interface. By default this is only done for C++ code.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>-[no]swig-lisp</td>
|
||||
<td>Turns on or off generation of code for helper lisp macro, functions,
|
||||
etc. which SWIG uses while generating wrappers. These macros, functions
|
||||
may still be used by generated wrapper code.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<H3><a name="Lisp_nn5">29.2.2 Generating CFFI bindings</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
|
||||
As we mentioned earlier the ideal way to use SWIG is to use interface
|
||||
files. To illustrate the use of it, let's assume that we have a
|
||||
file named <i>test.h</i> with the following C code:
|
||||
</p>
|
||||
|
||||
<div class="code"><pre>
|
||||
#define y 5
|
||||
#define x (y >> 1)
|
||||
|
||||
typedef int days;
|
||||
|
||||
struct bar {
|
||||
short p, q;
|
||||
char a, b;
|
||||
int *z[1000];
|
||||
struct bar * n;
|
||||
};
|
||||
|
||||
struct bar * my_struct;
|
||||
|
||||
struct foo {
|
||||
int a;
|
||||
struct foo * b[100];
|
||||
};
|
||||
|
||||
int pointer_func(void (*ClosureFun)( void* _fun, void* _data, void* _evt ), int p);
|
||||
|
||||
int func123(div_t * p, int **q[100], int r[][1000][10]);
|
||||
|
||||
void lispsort_double (int n, double * array);
|
||||
|
||||
enum color { RED, BLUE, GREEN};
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
Corresponding to this we will write a simple interface file:
|
||||
</p>
|
||||
|
||||
<div class="code"><pre>
|
||||
%module test
|
||||
|
||||
%include "test.h"
|
||||
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
The generated SWIG Code will be:
|
||||
</p>
|
||||
|
||||
<div class="targetlang"><pre>
|
||||
;;;SWIG wrapper code starts here
|
||||
|
||||
(cl:defmacro defanonenum (&body enums)
|
||||
"Converts anonymous enums to defconstants."
|
||||
`(cl:progn , @(cl:loop for value in enums
|
||||
for index = 0 then (cl:1+ index)
|
||||
when (cl:listp value) do (cl:setf index (cl:second value)
|
||||
value (cl:first value))
|
||||
collect `(cl:defconstant , value , index))))
|
||||
|
||||
(cl:eval-when (:compile-toplevel :load-toplevel)
|
||||
(cl:unless (cl:fboundp 'swig-lispify)
|
||||
(cl:defun swig-lispify (name flag cl:&optional (package cl:*package*))
|
||||
(cl:labels ((helper (lst last rest cl:&aux (c (cl:car lst)))
|
||||
(cl:cond
|
||||
((cl:null lst)
|
||||
rest)
|
||||
((cl:upper-case-p c)
|
||||
(helper (cl:cdr lst) 'upper
|
||||
(cl:case last
|
||||
((lower digit) (cl:list* c #\- rest))
|
||||
(cl:t (cl:cons c rest)))))
|
||||
((cl:lower-case-p c)
|
||||
(helper (cl:cdr lst) 'lower (cl:cons (cl:char-upcase c) rest)))
|
||||
((cl:digit-char-p c)
|
||||
(helper (cl:cdr lst) 'digit
|
||||
(cl:case last
|
||||
((upper lower) (cl:list* c #\- rest))
|
||||
(cl:t (cl:cons c rest)))))
|
||||
((cl:char-equal c #\_)
|
||||
(helper (cl:cdr lst) '_ (cl:cons #\- rest)))
|
||||
(cl:t
|
||||
(cl:error "Invalid character: ~A" c)))))
|
||||
(cl:let ((fix (cl:case flag
|
||||
((constant enumvalue) "+")
|
||||
(variable "*")
|
||||
(cl:t ""))))
|
||||
(cl:intern
|
||||
(cl:concatenate
|
||||
'cl:string
|
||||
fix
|
||||
(cl:nreverse (helper (cl:concatenate 'cl:list name) cl:nil cl:nil))
|
||||
fix)
|
||||
package))))))
|
||||
|
||||
;;;SWIG wrapper code ends here
|
||||
|
||||
|
||||
(cl:defconstant y 5)
|
||||
|
||||
(cl:defconstant x (cl:ash 5 -1))
|
||||
|
||||
(cffi:defcstruct bar
|
||||
(p :short)
|
||||
(q :short)
|
||||
(a :char)
|
||||
(b :char)
|
||||
(z :pointer)
|
||||
(n :pointer))
|
||||
|
||||
(cffi:defcvar ("my_struct" my_struct)
|
||||
:pointer)
|
||||
|
||||
(cffi:defcstruct foo
|
||||
(a :int)
|
||||
(b :pointer))
|
||||
|
||||
(cffi:defcfun ("pointer_func" pointer_func) :int
|
||||
(ClosureFun :pointer)
|
||||
(p :int))
|
||||
|
||||
(cffi:defcfun ("func123" func123) :int
|
||||
(p :pointer)
|
||||
(q :pointer)
|
||||
(r :pointer))
|
||||
|
||||
(cffi:defcfun ("lispsort_double" lispsort_double) :void
|
||||
(n :int)
|
||||
(array :pointer))
|
||||
|
||||
(cffi:defcenum color
|
||||
:RED
|
||||
:BLUE
|
||||
:GREEN)
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
The <i>SWIG wrapper</i> code refers to the special code which SWIG
|
||||
may need to use while wrapping C code. You can turn on/off the
|
||||
generation of this code by using the <i>-[no]swig-lisp</i>
|
||||
option. You must have noticed that SWIG goes one extra step to
|
||||
ensure that CFFI does not do automatic lispification of the C
|
||||
function names. The reason SWIG does this is because quite often
|
||||
developers want to build a nice CLOS based lispy API, and this one
|
||||
to one correspondence between C function names and lisp function
|
||||
name helps.
|
||||
</p>
|
||||
|
||||
<p> Maybe you want to have your own convention for generating lisp
|
||||
function names for corresponding C function names, or you just
|
||||
want to lispify the names, also, before we forget you want to
|
||||
export the generated lisp names. To do this, we will use the
|
||||
SWIG <a
|
||||
href="Customization.html#Customization_features">feature directive</a>.
|
||||
Let's edit the interface file such that the C type "div_t*" is changed
|
||||
to Lisp type ":my-pointer", we lispify all names,
|
||||
export everything, and do some more stuff.
|
||||
|
||||
</p>
|
||||
<div class="code"><pre>
|
||||
%module test
|
||||
|
||||
%typemap(cin) div_t* ":my-pointer"
|
||||
|
||||
%feature("intern_function", "1");
|
||||
%feature("export");
|
||||
|
||||
%feature("inline") lispsort_double;
|
||||
%feature("intern_function", "my-lispify") lispsort_double;
|
||||
%feature("export", package="'some-other-package") lispsort_double;
|
||||
|
||||
%rename func123 renamed_cool_func;
|
||||
|
||||
%ignore "pointer_func";
|
||||
|
||||
%include "test.h"
|
||||
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
The <i>typemap(cin)</i> ensures that for all arguments which are input
|
||||
to C with the type "div_t*", the ":my-pointer" type be
|
||||
used. Similarly <i>typemap(cout)</i> are used for all types which
|
||||
are returned from C.
|
||||
</p>
|
||||
<p>
|
||||
The feature <i>intern_function</i> ensures that all C names are
|
||||
interned using the <b>swig-lispify</b> function. The "1" given
|
||||
to the feature is optional. The use of feature like
|
||||
<i>%feature("intern_function", "1");</i> globally enables
|
||||
interning for everything. If you want to target a single
|
||||
function, or declaration then use the targeted version of
|
||||
feature, <i>%feature("intern_function", "my-lispify")
|
||||
lispsort_double;</i>, here we are using an additional feature
|
||||
which allows us to use our lispify function.
|
||||
</p>
|
||||
<p>The <i>export</i> feature allows us to export the symbols. If
|
||||
the <i>package</i> argument is given, then the symbol will be exported to
|
||||
the specified Lisp package. The <i>inline</i> feature declaims the
|
||||
declared function as inline. The <i>rename</i> directive allows us to
|
||||
change the name(it is useful when generating C wrapper code for handling
|
||||
overloaded functions). The <i>ignore</i> directive ignores a certain
|
||||
declaration.
|
||||
</p>
|
||||
<p>There are several other things which are possible, to see some
|
||||
example of usage of SWIG look at the Lispbuilder and wxCL
|
||||
projects. The generated code with 'noswig-lisp' option is:
|
||||
</p>
|
||||
|
||||
<div class="targetlang"><pre>
|
||||
(cl:defconstant #.(swig-lispify "y" 'constant) 5)
|
||||
|
||||
(cl:export '#.(swig-lispify "y" 'constant))
|
||||
|
||||
(cl:defconstant #.(swig-lispify "x" 'constant) (cl:ash 5 -1))
|
||||
|
||||
(cl:export '#.(swig-lispify "x" 'constant))
|
||||
|
||||
(cffi:defcstruct #.(swig-lispify "bar" 'classname)
|
||||
(#.(swig-lispify "p" 'slotname) :short)
|
||||
(#.(swig-lispify "q" 'slotname) :short)
|
||||
(#.(swig-lispify "a" 'slotname) :char)
|
||||
(#.(swig-lispify "b" 'slotname) :char)
|
||||
(#.(swig-lispify "z" 'slotname) :pointer)
|
||||
(#.(swig-lispify "n" 'slotname) :pointer))
|
||||
|
||||
(cl:export '#.(swig-lispify "bar" 'classname))
|
||||
|
||||
(cl:export '#.(swig-lispify "p" 'slotname))
|
||||
|
||||
(cl:export '#.(swig-lispify "q" 'slotname))
|
||||
|
||||
(cl:export '#.(swig-lispify "a" 'slotname))
|
||||
|
||||
(cl:export '#.(swig-lispify "b" 'slotname))
|
||||
|
||||
(cl:export '#.(swig-lispify "z" 'slotname))
|
||||
|
||||
(cl:export '#.(swig-lispify "n" 'slotname))
|
||||
|
||||
(cffi:defcvar ("my_struct" #.(swig-lispify "my_struct" 'variable))
|
||||
:pointer)
|
||||
|
||||
(cl:export '#.(swig-lispify "my_struct" 'variable))
|
||||
|
||||
(cffi:defcstruct #.(swig-lispify "foo" 'classname)
|
||||
(#.(swig-lispify "a" 'slotname) :int)
|
||||
(#.(swig-lispify "b" 'slotname) :pointer))
|
||||
|
||||
(cl:export '#.(swig-lispify "foo" 'classname))
|
||||
|
||||
(cl:export '#.(swig-lispify "a" 'slotname))
|
||||
|
||||
(cl:export '#.(swig-lispify "b" 'slotname))
|
||||
|
||||
(cffi:defcfun ("renamed_cool_func" #.(swig-lispify "renamed_cool_func" 'function)) :int
|
||||
(p :my-pointer)
|
||||
(q :pointer)
|
||||
(r :pointer))
|
||||
|
||||
(cl:export '#.(swig-lispify "renamed_cool_func" 'function))
|
||||
|
||||
(cl:declaim (cl:inline #.(my-lispify "lispsort_double" 'function)))
|
||||
|
||||
(cffi:defcfun ("lispsort_double" #.(my-lispify "lispsort_double" 'function)) :void
|
||||
(n :int)
|
||||
(array :pointer))
|
||||
|
||||
(cl:export '#.(my-lispify "lispsort_double" 'function) 'some-other-package)
|
||||
|
||||
(cffi:defcenum #.(swig-lispify "color" 'enumname)
|
||||
#.(swig-lispify "RED" 'enumvalue :keyword)
|
||||
#.(swig-lispify "BLUE" 'enumvalue :keyword)
|
||||
#.(swig-lispify "GREEN" 'enumvalue :keyword))
|
||||
|
||||
(cl:export '#.(swig-lispify "color" 'enumname))
|
||||
|
||||
</pre></div>
|
||||
|
||||
<H3><a name="Lisp_nn6">29.2.3 Generating CFFI bindings for C++ code</a></H3>
|
||||
|
||||
|
||||
<p>This feature to SWIG (for CFFI) is very new and still far from
|
||||
complete. Pitch in with your patches, bug reports and feature
|
||||
requests to improve it.
|
||||
</p>
|
||||
<p> Generating bindings for C++ code, requires <i>-c++</i> option to be
|
||||
present and it first generates C binding which will wrap the C++
|
||||
code, and then generates the
|
||||
corresponding CFFI wrapper code. In the generated C wrapper
|
||||
code, you will often want to put your own C code, such as the
|
||||
code to include various files. This can be done by making use of
|
||||
"%{" and "%}" as shown below.
|
||||
</p>
|
||||
<div class="code"><pre>
|
||||
%{
|
||||
#include "Test/test.h"
|
||||
%}
|
||||
</pre></div>
|
||||
<p>
|
||||
Also, while parsing the C++ file and generating C wrapper code SWIG
|
||||
may need to be able to understand various symbols used in other
|
||||
header files. To help SWIG in doing this while ensuring that
|
||||
wrapper code is generated for the target file, use the "import"
|
||||
directive. The "include" directive specifies the target file for
|
||||
which wrapper code will be generated.
|
||||
</p>
|
||||
<div class="code"><pre>
|
||||
|
||||
%import "ancillary/header.h"
|
||||
|
||||
%include "target/header.h"
|
||||
|
||||
</pre></div>
|
||||
<p>
|
||||
Various features which were available for C headers can also be used
|
||||
here. The target header which we are going to use here is:
|
||||
</p>
|
||||
<div class="code"><pre>
|
||||
namespace OpenDemo {
|
||||
class Test
|
||||
{
|
||||
public:
|
||||
float x;
|
||||
// constructors
|
||||
Test (void) {x = 0;}
|
||||
Test (float X) {x = X;}
|
||||
|
||||
// vector addition
|
||||
Test operator+ (const Test& v) const {return Test (x+v.x);}
|
||||
|
||||
// length squared
|
||||
float lengthSquared (void) const {return this->dot (*this);}
|
||||
|
||||
static float distance (const Test& a, const Test& b){return(a-b).length();}
|
||||
|
||||
inline Test parallelComponent (const Test& unitBasis) const {
|
||||
return unitBasis * projection;
|
||||
}
|
||||
|
||||
Test setYtoZero (void) const {return Test (this->x);}
|
||||
|
||||
static const Test zero;
|
||||
};
|
||||
|
||||
inline Test operator* (float s, const Test& v) {return v*s;}
|
||||
|
||||
inline std::ostream& operator<< (std::ostream& o, const Test& v)
|
||||
{
|
||||
return o << "(" << v.x << ")";
|
||||
}
|
||||
|
||||
inline Test RandomUnitVectorOnXZPlane (void)
|
||||
{
|
||||
return RandomVectorInUnitRadiusSphere().setYtoZero().normalize();
|
||||
}
|
||||
}
|
||||
</pre></div>
|
||||
<p>The interface used is: </p>
|
||||
<div class="code"><pre>
|
||||
%module test
|
||||
%include "test.cpp"
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
SWIG generates 3 files, the first one is a C wrap which we don't show,
|
||||
the second is the plain CFFI wrapper which is as shown below:
|
||||
</p>
|
||||
<div class="targetlang"><pre>
|
||||
(cffi:defcfun ("_wrap_Test_x_set" Test_x_set) :void
|
||||
(self :pointer)
|
||||
(x :float))
|
||||
|
||||
(cffi:defcfun ("_wrap_Test_x_get" Test_x_get) :float
|
||||
(self :pointer))
|
||||
|
||||
(cffi:defcfun ("_wrap_new_Test__SWIG_0" new_Test) :pointer)
|
||||
|
||||
(cffi:defcfun ("_wrap_new_Test__SWIG_1" new_Test) :pointer
|
||||
(X :float))
|
||||
|
||||
(cffi:defcfun ("_wrap_Test___add__" Test___add__) :pointer
|
||||
(self :pointer)
|
||||
(v :pointer))
|
||||
|
||||
(cffi:defcfun ("_wrap_Test_lengthSquared" Test_lengthSquared) :float
|
||||
(self :pointer))
|
||||
|
||||
(cffi:defcfun ("_wrap_Test_distance" Test_distance) :float
|
||||
(a :pointer)
|
||||
(b :pointer))
|
||||
|
||||
(cffi:defcfun ("_wrap_Test_parallelComponent" Test_parallelComponent) :pointer
|
||||
(self :pointer)
|
||||
(unitBasis :pointer))
|
||||
|
||||
(cffi:defcfun ("_wrap_Test_setYtoZero" Test_setYtoZero) :pointer
|
||||
(self :pointer))
|
||||
|
||||
(cffi:defcvar ("Test_zero" Test_zero)
|
||||
:pointer)
|
||||
|
||||
(cffi:defcfun ("_wrap_delete_Test" delete_Test) :void
|
||||
(self :pointer))
|
||||
|
||||
(cffi:defcfun ("_wrap___mul__" __mul__) :pointer
|
||||
(s :float)
|
||||
(v :pointer))
|
||||
|
||||
(cffi:defcfun ("_wrap___lshift__" __lshift__) :pointer
|
||||
(o :pointer)
|
||||
(v :pointer))
|
||||
|
||||
(cffi:defcfun ("_wrap_RandomUnitVectorOnXZPlane" RandomUnitVectorOnXZPlane) :pointer)
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
The output is pretty good but it fails in disambiguating overloaded
|
||||
functions such as the constructor, in this case. One way of
|
||||
resolving this problem is to make the interface use the rename
|
||||
directiv, but hopefully there are better solutions.
|
||||
In addition SWIG also generates, a CLOS file
|
||||
</p>
|
||||
|
||||
|
||||
<div class="targetlang"><pre>
|
||||
(clos:defclass test()
|
||||
((ff :reader ff-pointer)))
|
||||
|
||||
(clos:defmethod (cl:setf x) (arg0 (obj test))
|
||||
(Test_x_set (ff-pointer obj) arg0))
|
||||
|
||||
(clos:defmethod x ((obj test))
|
||||
(Test_x_get (ff-pointer obj)))
|
||||
|
||||
(cl:shadow "+")
|
||||
(clos:defmethod + ((obj test) (self test) (v test))
|
||||
(Test___add__ (ff-pointer obj) (ff-pointer self) (ff-pointer v)))
|
||||
|
||||
(clos:defmethod length-squared ((obj test) (self test))
|
||||
(Test_lengthSquared (ff-pointer obj) (ff-pointer self)))
|
||||
|
||||
(clos:defmethod parallel-component ((obj test) (self test) (unitBasis test))
|
||||
(Test_parallelComponent (ff-pointer obj) (ff-pointer self) (ff-pointer unitBasis)))
|
||||
|
||||
(clos:defmethod set-yto-zero ((obj test) (self test))
|
||||
(Test_setYtoZero (ff-pointer obj) (ff-pointer self)))
|
||||
</pre></div>
|
||||
|
||||
<p>I agree that the CFFI C++ module needs lot more work. But I hope it
|
||||
provides a starting point, on which you can base your work of
|
||||
importing C++ libraries to Lisp.
|
||||
</p>
|
||||
<p>
|
||||
If you have any questions, suggestions, patches, etc., related to CFFI
|
||||
module feel free to contact us on the SWIG mailing list, and
|
||||
also please add a "[CFFI]" tag in the subject line.
|
||||
|
||||
<H3><a name="Lisp_nn7">29.2.4 Inserting user code into generated files</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
It is often necessary to <a href="SWIG.html#SWIG_nn40">include user-defined code</a>
|
||||
into the automatically generated interface files. For example, when building
|
||||
a C++ interface, example_wrap.cxx will likely not compile unless
|
||||
you add a <tt>#include "header.h"</tt> directive. This can be done
|
||||
using the SWIG <tt>%insert(section) %{ ...code... %}</tt> directive:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%module example
|
||||
|
||||
%{
|
||||
#include "header.h"
|
||||
%}
|
||||
|
||||
%include "header.h"
|
||||
|
||||
int fact(int n);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Additional sections have been added for inserting into the
|
||||
generated lisp interface file:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>lisphead</tt> - inserts before type declarations</li>
|
||||
<li><tt>swiglisp</tt> - inserts after type declarations according to
|
||||
where it appears in the .i file</li>
|
||||
</ul>
|
||||
<p>
|
||||
Note that the block <tt>%{ ... %}</tt> is effectively a shortcut for
|
||||
<tt>%insert("header") %{ ... %}</tt>.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -202,46 +202,6 @@ android_clean:
|
|||
rm -f `find $(PACKAGEDIR) -name \*.java | grep -v $(PROJECTNAME).java`
|
||||
rm -rf obj
|
||||
|
||||
##################################################################
|
||||
##### CFFI ######
|
||||
##################################################################
|
||||
|
||||
CFFI = @CFFIBIN@
|
||||
CFFI_SCRIPT=$(RUNME).lisp
|
||||
|
||||
cffi: $(SRCDIR_SRCS)
|
||||
$(SWIG) -cffi $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH)
|
||||
# $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCDIR_SRCS)
|
||||
# $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO)
|
||||
|
||||
cffi_cpp: $(SRCDIR_SRCS)
|
||||
$(SWIG) -c++ -cffi $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH)
|
||||
$(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES)
|
||||
$(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO)
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Run CFFI example
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
cffi_run:
|
||||
$(RUNTOOL) $(CFFI) -batch -s $(CFFI_SCRIPT) $(RUNPIPE)
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Version display
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
cffi_version:
|
||||
$(CFFI) --version
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Cleaning the CFFI examples
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
cffi_clean:
|
||||
rm -f *_wrap* *~ .~*
|
||||
rm -f core @EXTRA_CLEAN@
|
||||
rm -f *.@OBJEXT@ *@SO@
|
||||
|
||||
##################################################################
|
||||
##### CSHARP ######
|
||||
##################################################################
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
#######################################################################
|
||||
# Makefile for cffi test-suite
|
||||
#######################################################################
|
||||
|
||||
LANGUAGE = cffi
|
||||
CFFI = @CFFIBIN@
|
||||
SCRIPTSUFFIX = _runme.lisp
|
||||
|
||||
HAVE_CXX11 = @HAVE_CXX11@
|
||||
HAVE_CXX14 = @HAVE_CXX14@
|
||||
HAVE_CXX17 = @HAVE_CXX17@
|
||||
HAVE_CXX20 = @HAVE_CXX20@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
include $(srcdir)/../common.mk
|
||||
|
||||
# Overridden variables here
|
||||
# no C++ tests for now
|
||||
CPP_TEST_CASES =
|
||||
#C_TEST_CASES +=
|
||||
|
||||
# Custom tests - tests with additional commandline options
|
||||
# none!
|
||||
|
||||
# Rules for the different types of tests
|
||||
%.cpptest:
|
||||
$(setup)
|
||||
+$(swig_and_compile_cpp)
|
||||
$(run_testcase)
|
||||
|
||||
%.ctest:
|
||||
$(setup)
|
||||
+$(swig_and_compile_c)
|
||||
$(run_testcase)
|
||||
|
||||
%.multicpptest:
|
||||
$(setup)
|
||||
+$(swig_and_compile_multi_cpp)
|
||||
$(run_testcase)
|
||||
|
||||
# Runs the testcase. A testcase is only run if
|
||||
# a file is found which has _runme.lisp appended after the testcase name.
|
||||
run_testcase = \
|
||||
if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \
|
||||
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(CFFI) -batch -s $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \
|
||||
fi
|
||||
|
||||
# Clean: (does nothing, we don't generate extra cffi code)
|
||||
%.clean:
|
||||
@exit 0
|
||||
|
||||
clean:
|
||||
$(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' cffi_clean
|
||||
|
|
@ -1,286 +0,0 @@
|
|||
/* Define a C preprocessor symbol that can be used in interface files
|
||||
to distinguish between the SWIG language modules. */
|
||||
|
||||
#define SWIG_CFFI
|
||||
|
||||
/* Typespecs for basic types. */
|
||||
|
||||
%typemap(cin) void ":void"
|
||||
|
||||
%typemap(cin) char ":char"
|
||||
%typemap(cin) char * ":string"
|
||||
%typemap(cin) unsigned char ":unsigned-char"
|
||||
%typemap(cin) signed char ":char"
|
||||
|
||||
%typemap(cin) short ":short"
|
||||
%typemap(cin) signed short ":short"
|
||||
%typemap(cin) unsigned short ":unsigned-short"
|
||||
|
||||
%typemap(cin) int ":int"
|
||||
%typemap(cin) signed int ":int"
|
||||
%typemap(cin) unsigned int ":unsigned-int"
|
||||
|
||||
%typemap(cin) long ":long"
|
||||
%typemap(cin) signed long ":long"
|
||||
%typemap(cin) unsigned long ":unsigned-long"
|
||||
|
||||
%typemap(cin) long long ":long-long"
|
||||
%typemap(cin) signed long long ":long-long"
|
||||
%typemap(cin) unsigned long long ":unsigned-long-long"
|
||||
|
||||
%typemap(cin) float ":float"
|
||||
%typemap(cin) double ":double"
|
||||
%typemap(cin) SWIGTYPE ":pointer"
|
||||
|
||||
%typemap(cout) void ":void"
|
||||
|
||||
%typemap(cout) char ":char"
|
||||
%typemap(cout) char * ":string"
|
||||
%typemap(cout) unsigned char ":unsigned-char"
|
||||
%typemap(cout) signed char ":char"
|
||||
|
||||
%typemap(cout) short ":short"
|
||||
%typemap(cout) signed short ":short"
|
||||
%typemap(cout) unsigned short ":unsigned-short"
|
||||
|
||||
%typemap(cout) int ":int"
|
||||
%typemap(cout) signed int ":int"
|
||||
%typemap(cout) unsigned int ":unsigned-int"
|
||||
|
||||
%typemap(cout) long ":long"
|
||||
%typemap(cout) signed long ":long"
|
||||
%typemap(cout) unsigned long ":unsigned-long"
|
||||
|
||||
%typemap(cout) long long ":long-long"
|
||||
%typemap(cout) signed long long ":long-long"
|
||||
%typemap(cout) unsigned long long ":unsigned-long-long"
|
||||
|
||||
%typemap(cout) float ":float"
|
||||
%typemap(cout) double ":double"
|
||||
%typemap(cout) SWIGTYPE ":pointer"
|
||||
|
||||
|
||||
%typemap(ctype) bool "int"
|
||||
%typemap(ctype) char, unsigned char, signed char,
|
||||
short, signed short, unsigned short,
|
||||
int, signed int, unsigned int,
|
||||
long, signed long, unsigned long,
|
||||
float, double, long double, char *, void *, void,
|
||||
enum SWIGTYPE, SWIGTYPE *,
|
||||
SWIGTYPE[ANY], SWIGTYPE &, SWIGTYPE && "$1_ltype";
|
||||
%typemap(ctype) SWIGTYPE "$&1_type"
|
||||
|
||||
%typemap(in) bool "$1 = (bool)$input;"
|
||||
%typemap(in) char, unsigned char, signed char,
|
||||
short, signed short, unsigned short,
|
||||
int, signed int, unsigned int,
|
||||
long, signed long, unsigned long,
|
||||
float, double, long double, char *, void *, void,
|
||||
enum SWIGTYPE, SWIGTYPE *,
|
||||
SWIGTYPE[ANY], SWIGTYPE &, SWIGTYPE && "$1 = $input;";
|
||||
%typemap(in) SWIGTYPE "$1 = *$input;"
|
||||
|
||||
%typemap(out) void ""
|
||||
%typemap(out) bool "$result = (int)$1;"
|
||||
%typemap(out) char, unsigned char, signed char,
|
||||
short, signed short, unsigned short,
|
||||
int, signed int, unsigned int,
|
||||
long, signed long, unsigned long,
|
||||
float, double, long double, char *, void *,
|
||||
enum SWIGTYPE, SWIGTYPE *,
|
||||
SWIGTYPE[ANY], SWIGTYPE &, SWIGTYPE && "$result = $1;";
|
||||
#ifdef __cplusplus
|
||||
%typemap(out) SWIGTYPE
|
||||
%{ $result = new $1_ltype($1); %}
|
||||
#else
|
||||
%typemap(out) SWIGTYPE {
|
||||
$result = ($&1_ltype) malloc(sizeof($1_type));
|
||||
memmove($result, &$1, sizeof($1_type));
|
||||
}
|
||||
#endif
|
||||
|
||||
%typecheck(SWIG_TYPECHECK_BOOL) bool { $1 = 1; };
|
||||
%typecheck(SWIG_TYPECHECK_CHAR) char { $1 = 1; };
|
||||
%typecheck(SWIG_TYPECHECK_FLOAT) float { $1 = 1; };
|
||||
%typecheck(SWIG_TYPECHECK_DOUBLE) double { $1 = 1; };
|
||||
%typecheck(SWIG_TYPECHECK_STRING) char * { $1 = 1; };
|
||||
%typecheck(SWIG_TYPECHECK_INTEGER)
|
||||
unsigned char, signed char,
|
||||
short, signed short, unsigned short,
|
||||
int, signed int, unsigned int,
|
||||
long, signed long, unsigned long,
|
||||
enum SWIGTYPE { $1 = 1; };
|
||||
%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&,
|
||||
SWIGTYPE[ANY], SWIGTYPE { $1 = 1; };
|
||||
/* This maps C/C++ types to Lisp classes for overload dispatch */
|
||||
|
||||
%typemap(lisptype) bool "cl:boolean"
|
||||
%typemap(lisptype) char "cl:character"
|
||||
%typemap(lisptype) unsigned char "cl:integer"
|
||||
%typemap(lisptype) signed char "cl:integer"
|
||||
|
||||
%typemap(lispclass) bool "t"
|
||||
%typemap(lispclass) char "cl:character"
|
||||
%typemap(lispclass) unsigned char, signed char,
|
||||
short, signed short, unsigned short,
|
||||
int, signed int, unsigned int,
|
||||
long, signed long, unsigned long,
|
||||
enum SWIGTYPE "cl:integer";
|
||||
/* CLOS methods can't be specialized on single-float or double-float */
|
||||
%typemap(lispclass) float "cl:number"
|
||||
%typemap(lispclass) double "cl:number"
|
||||
%typemap(lispclass) char * "cl:string"
|
||||
|
||||
/* Array reference typemaps */
|
||||
%apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) }
|
||||
%apply SWIGTYPE && { SWIGTYPE ((&&)[ANY]) }
|
||||
|
||||
/* const pointers */
|
||||
%apply SWIGTYPE * { SWIGTYPE *const }
|
||||
%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) }
|
||||
%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) }
|
||||
|
||||
%{
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define EXTERN extern "C"
|
||||
#else
|
||||
# define EXTERN extern
|
||||
#endif
|
||||
|
||||
#define EXPORT EXTERN SWIGEXPORT
|
||||
|
||||
#include <string.h>
|
||||
%}
|
||||
|
||||
%insert("swiglisp") %{
|
||||
;;;SWIG wrapper code starts here
|
||||
|
||||
(cl:defmacro defanonenum (cl:&body enums)
|
||||
"Converts anonymous enums to defconstants."
|
||||
`(cl:progn ,@(cl:loop for value in enums
|
||||
for index = 0 then (cl:1+ index)
|
||||
when (cl:listp value) do (cl:setf index (cl:second value)
|
||||
value (cl:first value))
|
||||
collect `(cl:defconstant ,value ,index))))
|
||||
|
||||
(cl:eval-when (:compile-toplevel :load-toplevel)
|
||||
(cl:unless (cl:fboundp 'swig-lispify)
|
||||
(cl:defun swig-lispify (name flag cl:&optional (package cl:*package*))
|
||||
(cl:labels ((helper (lst last rest cl:&aux (c (cl:car lst)))
|
||||
(cl:cond
|
||||
((cl:null lst)
|
||||
rest)
|
||||
((cl:upper-case-p c)
|
||||
(helper (cl:cdr lst) 'upper
|
||||
(cl:case last
|
||||
((lower digit) (cl:list* c #\- rest))
|
||||
(cl:t (cl:cons c rest)))))
|
||||
((cl:lower-case-p c)
|
||||
(helper (cl:cdr lst) 'lower (cl:cons (cl:char-upcase c) rest)))
|
||||
((cl:digit-char-p c)
|
||||
(helper (cl:cdr lst) 'digit
|
||||
(cl:case last
|
||||
((upper lower) (cl:list* c #\- rest))
|
||||
(cl:t (cl:cons c rest)))))
|
||||
((cl:char-equal c #\_)
|
||||
(helper (cl:cdr lst) '_ (cl:cons #\- rest)))
|
||||
(cl:t
|
||||
(cl:error "Invalid character: ~A" c)))))
|
||||
(cl:let ((fix (cl:case flag
|
||||
((constant enumvalue) "+")
|
||||
(variable "*")
|
||||
(cl:t ""))))
|
||||
(cl:intern
|
||||
(cl:concatenate
|
||||
'cl:string
|
||||
fix
|
||||
(cl:nreverse (helper (cl:concatenate 'cl:list name) cl:nil cl:nil))
|
||||
fix)
|
||||
package))))))
|
||||
|
||||
;;;SWIG wrapper code ends here
|
||||
%}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
/* name conversion for overloaded operators. */
|
||||
#ifdef __cplusplus
|
||||
%rename(__add__) *::operator+;
|
||||
%rename(__pos__) *::operator+();
|
||||
%rename(__pos__) *::operator+() const;
|
||||
|
||||
%rename(__sub__) *::operator-;
|
||||
%rename(__neg__) *::operator-() const;
|
||||
%rename(__neg__) *::operator-();
|
||||
|
||||
%rename(__mul__) *::operator*;
|
||||
%rename(__deref__) *::operator*();
|
||||
%rename(__deref__) *::operator*() const;
|
||||
|
||||
%rename(__div__) *::operator/;
|
||||
%rename(__mod__) *::operator%;
|
||||
%rename(__logxor__) *::operator^;
|
||||
%rename(__logand__) *::operator&;
|
||||
%rename(__logior__) *::operator|;
|
||||
%rename(__lognot__) *::operator~();
|
||||
%rename(__lognot__) *::operator~() const;
|
||||
|
||||
%rename(__not__) *::operator!();
|
||||
%rename(__not__) *::operator!() const;
|
||||
|
||||
%rename(__assign__) *::operator=;
|
||||
|
||||
%rename(__add_assign__) *::operator+=;
|
||||
%rename(__sub_assign__) *::operator-=;
|
||||
%rename(__mul_assign__) *::operator*=;
|
||||
%rename(__div_assign__) *::operator/=;
|
||||
%rename(__mod_assign__) *::operator%=;
|
||||
%rename(__logxor_assign__) *::operator^=;
|
||||
%rename(__logand_assign__) *::operator&=;
|
||||
%rename(__logior_assign__) *::operator|=;
|
||||
|
||||
%rename(__lshift__) *::operator<<;
|
||||
%rename(__lshift_assign__) *::operator<<=;
|
||||
%rename(__rshift__) *::operator>>;
|
||||
%rename(__rshift_assign__) *::operator>>=;
|
||||
|
||||
%rename(__eq__) *::operator==;
|
||||
%rename(__ne__) *::operator!=;
|
||||
%rename(__lt__) *::operator<;
|
||||
%rename(__gt__) *::operator>;
|
||||
%rename(__lte__) *::operator<=;
|
||||
%rename(__gte__) *::operator>=;
|
||||
|
||||
%rename(__and__) *::operator&&;
|
||||
%rename(__or__) *::operator||;
|
||||
|
||||
%rename(__preincr__) *::operator++();
|
||||
%rename(__postincr__) *::operator++(int);
|
||||
%rename(__predecr__) *::operator--();
|
||||
%rename(__postdecr__) *::operator--(int);
|
||||
|
||||
%rename(__comma__) *::operator,();
|
||||
%rename(__comma__) *::operator,() const;
|
||||
|
||||
%rename(__member_ref__) *::operator->;
|
||||
%rename(__member_func_ref__) *::operator->*;
|
||||
|
||||
%rename(__funcall__) *::operator();
|
||||
%rename(__aref__) *::operator[];
|
||||
#endif
|
||||
|
||||
|
||||
%{
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define EXTERN extern "C"
|
||||
#else
|
||||
# define EXTERN extern
|
||||
#endif
|
||||
|
||||
#define EXPORT EXTERN SWIGEXPORT
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
%}
|
||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue