|
From: Akshay S. <ak...@us...> - 2013-01-20 07:41:49
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "matlisp".
The branch, tensor has been updated
via 4862a338530bb1b435f2d6535913abe9947931b6 (commit)
from 657120d7a8bc0b0e26bbb522697e75c9f5b92ec1 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 4862a338530bb1b435f2d6535913abe9947931b6
Author: Akshay Srinivasan <aks...@gm...>
Date: Sat Jan 19 23:36:28 2013 -0800
o Wrapped some functions inside (eval-when ..).
diff --git a/src/ffi/f77-ffi.lisp b/src/ffi/f77-ffi.lisp
index 177f431..301520e 100644
--- a/src/ffi/f77-ffi.lisp
+++ b/src/ffi/f77-ffi.lisp
@@ -10,322 +10,118 @@
(in-package #:matlisp-ffi)
-
-(definline %f77.string-p (type)
- "
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (definline %f77.string-p (type)
+ "
Checks if the given type is a string."
- (eq type :string))
+ (eq type :string))
-(definline %f77.array-p (type)
- "
+ (definline %f77.array-p (type)
+ "
Checks if the given type is an array."
- (and (listp type) (eq (car type) '*)))
+ (and (listp type) (eq (car type) '*)))
-(definline %f77.cast-as-array-p (type)
- "
+ (definline %f77.cast-as-array-p (type)
+ "
Checks if the given type is - or has to be passed as - an array."
- (or (when (listp type)
- (eq (car type) '*))
- (eq type :complex-single-float)
- (eq type :complex-double-float)))
-
-;; Check if the given type is a callback.
-(definline %f77.callback-type-p (type)
- "
+ (or (when (listp type)
+ (eq (car type) '*))
+ (eq type :complex-single-float)
+ (eq type :complex-double-float)))
+
+ ;; Check if the given type is a callback.
+ (definline %f77.callback-type-p (type)
+ "
Checks if the given type is a callback"
- (and (listp type) (eq (first type) :callback)))
-
-;; Get the equivalent CFFI type.
-;; If the type is an array, get the type of the array element type.
-(defun %f77.cffi-type (type)
- "Convert the given matlisp-ffi type into one understood by CFFI."
- (cond
- ((and (listp type) (eq (first type) '*))
- `(:pointer ,(%f77.cffi-type (second type))))
- ((%f77.callback-type-p type)
- `(:pointer ,(%f77.cffi-type :callback)))
- ((eq type :complex-single-float)
- `(:pointer ,(%f77.cffi-type :single-float)))
- ((eq type :complex-double-float)
- `(:pointer ,(%f77.cffi-type :double-float)))
- (t (ecase type
- (:void :void)
- (:integer :int32)
- (:character :char)
- (:long :int64)
- (:single-float :float)
- (:double-float :double)
- (:string :string)
- ;; Pass a pointer to the function.
- (:callback :void)
- (t (error 'unknown-token :token type
- :message "Don't know the given Fortran type."))))))
-
-(defun %f77.get-return-type (type)
- "
+ (and (listp type) (eq (first type) :callback)))
+
+ ;; Get the equivalent CFFI type.
+ ;; If the type is an array, get the type of the array element type.
+ (defun %f77.cffi-type (type)
+ "Convert the given matlisp-ffi type into one understood by CFFI."
+ (cond
+ ((and (listp type) (eq (first type) '*))
+ `(:pointer ,(%f77.cffi-type (second type))))
+ ((%f77.callback-type-p type)
+ `(:pointer ,(%f77.cffi-type :callback)))
+ ((eq type :complex-single-float)
+ `(:pointer ,(%f77.cffi-type :single-float)))
+ ((eq type :complex-double-float)
+ `(:pointer ,(%f77.cffi-type :double-float)))
+ (t (ecase type
+ (:void :void)
+ (:integer :int32)
+ (:character :char)
+ (:long :int64)
+ (:single-float :float)
+ (:double-float :double)
+ (:string :string)
+ ;; Pass a pointer to the function.
+ (:callback :void)
+ (t (error 'unknown-token :token type
+ :message "Don't know the given Fortran type."))))))
+
+ (defun %f77.get-return-type (type)
+ "
Return type understood by CFFI. Note that unlike arguments fortran
functions return-by-value."
- (if (or (%f77.cast-as-array-p type) (%f77.callback-type-p type))
- (error 'invalid-type :given type :expected '(not (or (%f77.cast-as-array-p type)
- (%f77.callback-type-p type)))
- :message "A Fortran function cannot return the given type.")
- (%f77.cffi-type type)))
-
-(definline %f77.output-p (style)
- "
+ (if (or (%f77.cast-as-array-p type) (%f77.callback-type-p type))
+ (error 'invalid-type :given type :expected '(not (or (%f77.cast-as-array-p type)
+ (%f77.callback-type-p type)))
+ :message "A Fortran function cannot return the given type.")
+ (%f77.cffi-type type)))
+
+ (definline %f77.output-p (style)
+ "
Checks if style implies output."
- (member style '(:output :input-output :workspace-output)))
+ (member style '(:output :input-output :workspace-output)))
-(definline %f77.input-p (style)
- "
+ (definline %f77.input-p (style)
+ "
Checks if style implies input."
- (member style '(:input :input-value :input-reference :workspace)))
+ (member style '(:input :input-value :input-reference :workspace)))
-(defun %f77.get-read-in-type (type &optional (style :input))
- "
+ (defun %f77.get-read-in-type (type &optional (style :input))
+ "
Get the input type to be passed to CFFI."
- (assert (member style +ffi-styles+) nil 'unknown-token :token style
- :message "Don't know how to handle style.")
- (cond
- ;; Can't do much else if type is an array/complex or input is passed-by-value.
- ((or (%f77.callback-type-p type)
- (%f77.cast-as-array-p type)
- (eq style :input-value))
- (%f77.cffi-type type))
- ;; else pass-by-reference
- (t
- `(:pointer ,(%f77.cffi-type type)))))
-
-(defun %f77.parse-fortran-parameters (body)
- "
+ (assert (member style +ffi-styles+) nil 'unknown-token :token style
+ :message "Don't know how to handle style.")
+ (cond
+ ;; Can't do much else if type is an array/complex or input is passed-by-value.
+ ((or (%f77.callback-type-p type)
+ (%f77.cast-as-array-p type)
+ (eq style :input-value))
+ (%f77.cffi-type type))
+ ;; else pass-by-reference
+ (t
+ `(:pointer ,(%f77.cffi-type type)))))
+
+ (defun %f77.parse-fortran-parameters (body)
+ "
Parse fortran parameters and convert parameters to native C90 types (and
add additional function parameters)."
- (multiple-value-bind (doc pars)
- (parse-doc-&-parameters body)
- (declare (ignore doc))
-
- (let* ((aux-pars nil)
- (new-pars
- (mapcar #'(lambda (decl)
- (destructuring-bind (name type &optional (style :input-reference)) decl
- (case type
- (:string
- ;; String lengths are appended to the function arguments,
- ;; passed by value.
- (nconsc aux-pars `((,(scat "LEN-" name) ,(%f77.cffi-type :integer))))
- `(,name ,(%f77.cffi-type :string)))
- (t
- `(,name ,(%f77.get-read-in-type type style))))))
- pars)))
- `( ;; don't want documentation for direct interface, not useful
- ;; ,@doc
- ,@new-pars ,@aux-pars))))
-
-(defmacro def-fortran-routine (name-and-options return-type &rest body)
- "
- DEF-FORTRAN-ROUTINE
-
- An external Fortran routine definition form (DEF-FORTRAN-ROUTINE
- MY-FUN ...) creates two functions:
-
- 1. a raw FFI (foreign function interface),
- 2. an easier to use lisp interface to the raw interface.
-
- The documentation given here relates in the most part to the
- simplified lisp interface.
-
- Example:
- ========
- libblas.a contains the fortran subroutine DCOPY(N,X,INCX,Y,INCY)
- which copies the vector Y of N double-float's to the vector X.
- The function name in libblas.a is \"dcopy_\" (by Fortran convention).
-
- (DEF-FORTRAN-ROUTINE DCOPY :void
- (N :integer :input)
- (X (* :double-float) :output)
- (INCX :integer :input)
- (Y (* :double-float) :input)
- (INCY :integer :input))
-
- will expand into:
-
- (CFFI:DEFCFUN (\"dcopy_\" FORTRAN-DCOPY) :VOID
- (N :POINTER :INT)
- (DX :POINTER :DOUBLE)
- (INCX :POINTER :INT)
- (DY :POINTER :DOUBLE)
- (INCY :POINTER :INT))
-
- and
-
- (DEFUN DCOPY (N,X,INCX,Y,INCY)
- ...
-
- In turn, the lisp function DCOPY calls FORTRAN-DCOPY which calls
- the Fortran function \"dcopy_\" in libblas.a.
-
- Arguments:
- ==========
-
-
- NAME Name of the lisp interface function that will be created.
- The name of the raw FFI will be derived from NAME via
- the function MAKE-FFI-NAME. The name of foreign function
- (presumable a Fortran Function in an external library)
- will be derived from NAME via MAKE-FORTRAN-NAME.
-
- RETURN-TYPE
- The type of data that will be returned by the external
- (presumably Fortran) function.
-
- (MEMBER RETURN-TYPE '(:VOID :INTEGER :SINGLE-FLOAT :DOUBLE-FLOAT
- :COMPLEX-SINGLE-FLOAT :COMPLEX-DOUBLE-FLOAT))
-
- See GET-READ-OUT-TYPE.
-
- BODY A list of parameter forms. A parameter form is:
-
- (VARIABLE TYPE &optional (STYLE :INPUT))
-
- The VARIABLE is the name of a parameter accepted by the
- external (presumably Fortran) routine. TYPE is the type of
- VARIABLE. The recognized TYPE's are:
-
- TYPE Corresponds to Fortran Declaration
- ---- ----------------------------------
- :STRING CHARACTER*(*)
- :INTEGER INTEGER
- :SINGLE-FLOAT REAL
- :DOUBLE-FLOAT DOUBLE PRECISION
- :COMPLEX-SINGLE-FLOAT COMPLEX
- :COMPLEX-DOUBLE-FLOAT COMPLEX*16
- (* X) An array of type X.
- (:CALLBACK args) A description of a function or subroutine
-
- (MEMBER X '(:INTEGER :SINGLE-FLOAT :DOUBLE-FLOAT
- :COMPLEX-SINGLE-FLOAT :COMPLEX-DOUBLE-FLOAT)
-
-
- The STYLE (default :INPUT) defines how VARIABLE is treated.
- This is by far the most difficult quantity to learn. To
- begin with:
-
-
- (OR (MEMBER STYLE '(:INPUT :OUTPUT :INPUT-OUTPUT))
- (MEMBER STYLE '(:IN :COPY :IN-OUT :OUT)))
-
- TYPE STYLE Description
- ---- ----- -----------
- X :INPUT Value will be used but not modified.
-
- :OUTPUT Input value not used (but some value must be given),
- a value is returned as one of the values lisp
- function NAME. Similar to the :IN-OUT style
- of DEF-ALIEN-ROUTINE.
- :INPUT-OUTPUT Input value may be used, a value is returned
- as one of the values from the lisp function
- NAME.
-
- ** Note: In all 3 cases above the input VARIABLE will not be destroyed
- or modified directly, a copy is taken and a pointer of that
- copy is passed to the (presumably Fortran) external routine.
-
- (OR (* X) :INPUT Array entries are used but not modified.
- :STRING) :OUTPUT Array entries need not be initialized on input,
- but will be *modified*. In addition, the array
- will be returned via the Lisp command VALUES
- from the lisp function NAME.
-
- :INPUT-OUTPUT Like :OUTPUT but initial values on entry may be used.
-
- The keyword :WORKSPACE is a nickname for :INPUT. The
- keywords :INPUT-OR-OUTPUT, :WORKSPACE-OUTPUT,
- :WORKSPACE-OR-OUTPUT are nicknames for :OUTPUT.
-
- This is complicated. Suggestions are encouraged to
- interface a *functional language* to a *pass-by-reference
- language*.
-
- CALLBACKS
-
- A callback here means a function (or subroutine) that is passed into the Fortran
- routine which calls it as needed to compute something.
-
- The syntax of :CALLBACK is similar to the DEF-FORTRAN-ROUTINE:
-
- (name (:CALLBACK return-type
- {arg-description}))
-
- The RETURN-TYPE is the same as for DEF-FORTRAN-ROUTINE. The arg description is the
- same syntax as list of parameter forms for DEF-FORTRAN-ROUTINE. However, if the type
- is a pointer type (like (* :double-float)), then a required keyword option must be
- specified:
-
- (name (* type :size size) &optional style)
-
- The size specifies the total length of the Fortran array. This array is treated as a
- one dimentionsal vector and should be accessed using the function FV-REF, which is
- analogous to AREF. The SIZE parameter can be any Lisp form and can refer to any of the
- arguments to the Fortran routine.
-
- For example, a fortran routine can have the callback
-
- (def-fortran-routine foo :void
- (m (* :integer) :input)
- (fsub (:callback :void
- (x :double-float :input)
- (z (* :double-float :size (aref m 0)) :input)
- (f (* :double-float :size (aref m 0)) :output)))))
-
- This means that the arrays Z and F in FSUB have a dimension of (AREF M 0), the first
- element of the vector M. The function FSUB can be written in Lisp as
-
- (defun fsub (x z f)
- (setf (fv-ref f 0) (* x x (fv-ref z 3))))
-
- Further Notes:
- ===============
-
- Some Fortran routines use Fortran character strings in the
- parameter list. The definition here is suitable for Solaris
- where the Fortran character string is converted to a C-style null
- terminated string, AND an extra hidden parameter that is appended
- to the parameter list to hold the length of the string.
-
- If your Fortran does this differently, you'll have to change this
- definition accordingly!
-
- Call defcfun to define the foreign function.
- Also creates a nice lisp helper function."
- (multiple-value-bind (fortran-name name) (if (listp name-and-options)
- (values (car name-and-options) (cadr name-and-options))
- (values (make-fortran-name name-and-options) name-and-options))
- (let* ((lisp-name (make-fortran-ffi-name `,name))
- (hack-return-type `,return-type)
- (hack-body `(,@body))
- (hidden-var-name nil))
- ;;
- (multiple-value-bind (doc pars)
- (parse-doc-&-parameters `(,@body))
- (when (member hack-return-type '(:complex-single-float :complex-double-float))
- ;; The return type is complex. Since this is a "structure",
- ;; Fortran inserts a "hidden" first parameter before all
- ;; others. This is used to store the resulting complex
- ;; number. Then there is no "return" value, so set the return
- ;; type to :void.
- ;;
- (setq hidden-var-name (gensym "HIDDEN-COMPLEX-RETURN-"))
- (setq hack-body `(,@doc
- (,hidden-var-name ,hack-return-type :output)
- ,@pars))
- (setq hack-return-type :void)))
-
- `(progn
- (cffi:defcfun (,fortran-name ,lisp-name) ,(%f77.get-return-type hack-return-type)
- ,@(%f77.parse-fortran-parameters hack-body))
- ,@(%f77.def-fortran-interface name hack-return-type hack-body hidden-var-name)))))
-
-;; Create a form specifying a simple Lisp function that calls the
+ (multiple-value-bind (doc pars)
+ (parse-doc-&-parameters body)
+ (declare (ignore doc))
+
+ (let* ((aux-pars nil)
+ (new-pars
+ (mapcar #'(lambda (decl)
+ (destructuring-bind (name type &optional (style :input-reference)) decl
+ (case type
+ (:string
+ ;; String lengths are appended to the function arguments,
+ ;; passed by value.
+ (nconsc aux-pars `((,(scat "LEN-" name) ,(%f77.cffi-type :integer))))
+ `(,name ,(%f77.cffi-type :string)))
+ (t
+ `(,name ,(%f77.get-read-in-type type style))))))
+ pars)))
+ `( ;; don't want documentation for direct interface, not useful
+ ;; ,@doc
+ ,@new-pars ,@aux-pars))))
+
+ ;; Create a form specifying a simple Lisp function that calls the
;; underlying Fortran routine of the same name.
(defun %f77.def-fortran-interface (name return-type body hidden-var-name)
(multiple-value-bind (doc pars)
@@ -450,6 +246,9 @@
,@(mapcar #'second return-vars)))))))))
;;TODO: Outputs are messed up inside the callback
+;;TODO: Define callbacks outside the function call and lexically bind functions inside the
+;; call. Callbacks allocate memory in some non-GC'ed part of the heap. Runs out of memory
+;; quite quickly.
(defun %f77.def-fortran-callback (func callback-name return-type parm)
(let* ((hack-return-type `,return-type)
(hack-parm `(,@parm))
@@ -542,3 +341,208 @@
,(if (eq hack-return-type :void)
nil
retvar))))))))
+)
+
+(defmacro def-fortran-routine (name-and-options return-type &rest body)
+ "
+ DEF-FORTRAN-ROUTINE
+
+ An external Fortran routine definition form (DEF-FORTRAN-ROUTINE
+ MY-FUN ...) creates two functions:
+
+ 1. a raw FFI (foreign function interface),
+ 2. an easier to use lisp interface to the raw interface.
+
+ The documentation given here relates in the most part to the
+ simplified lisp interface.
+
+ Example:
+ ========
+ libblas.a contains the fortran subroutine DCOPY(N,X,INCX,Y,INCY)
+ which copies the vector Y of N double-float's to the vector X.
+ The function name in libblas.a is \"dcopy_\" (by Fortran convention).
+
+ (DEF-FORTRAN-ROUTINE DCOPY :void
+ (N :integer :input)
+ (X (* :double-float) :output)
+ (INCX :integer :input)
+ (Y (* :double-float) :input)
+ (INCY :integer :input))
+
+ will expand into:
+
+ (CFFI:DEFCFUN (\"dcopy_\" FORTRAN-DCOPY) :VOID
+ (N :POINTER :INT)
+ (DX :POINTER :DOUBLE)
+ (INCX :POINTER :INT)
+ (DY :POINTER :DOUBLE)
+ (INCY :POINTER :INT))
+
+ and
+
+ (DEFUN DCOPY (N,X,INCX,Y,INCY)
+ ...
+
+ In turn, the lisp function DCOPY calls FORTRAN-DCOPY which calls
+ the Fortran function \"dcopy_\" in libblas.a.
+
+ Arguments:
+ ==========
+
+
+ NAME Name of the lisp interface function that will be created.
+ The name of the raw FFI will be derived from NAME via
+ the function MAKE-FFI-NAME. The name of foreign function
+ (presumable a Fortran Function in an external library)
+ will be derived from NAME via MAKE-FORTRAN-NAME.
+
+ RETURN-TYPE
+ The type of data that will be returned by the external
+ (presumably Fortran) function.
+
+ (MEMBER RETURN-TYPE '(:VOID :INTEGER :SINGLE-FLOAT :DOUBLE-FLOAT
+ :COMPLEX-SINGLE-FLOAT :COMPLEX-DOUBLE-FLOAT))
+
+ See GET-READ-OUT-TYPE.
+
+ BODY A list of parameter forms. A parameter form is:
+
+ (VARIABLE TYPE &optional (STYLE :INPUT))
+
+ The VARIABLE is the name of a parameter accepted by the
+ external (presumably Fortran) routine. TYPE is the type of
+ VARIABLE. The recognized TYPE's are:
+
+ TYPE Corresponds to Fortran Declaration
+ ---- ----------------------------------
+ :STRING CHARACTER*(*)
+ :INTEGER INTEGER
+ :SINGLE-FLOAT REAL
+ :DOUBLE-FLOAT DOUBLE PRECISION
+ :COMPLEX-SINGLE-FLOAT COMPLEX
+ :COMPLEX-DOUBLE-FLOAT COMPLEX*16
+ (* X) An array of type X.
+ (:CALLBACK args) A description of a function or subroutine
+
+ (MEMBER X '(:INTEGER :SINGLE-FLOAT :DOUBLE-FLOAT
+ :COMPLEX-SINGLE-FLOAT :COMPLEX-DOUBLE-FLOAT)
+
+
+ The STYLE (default :INPUT) defines how VARIABLE is treated.
+ This is by far the most difficult quantity to learn. To
+ begin with:
+
+
+ (OR (MEMBER STYLE '(:INPUT :OUTPUT :INPUT-OUTPUT))
+ (MEMBER STYLE '(:IN :COPY :IN-OUT :OUT)))
+
+ TYPE STYLE Description
+ ---- ----- -----------
+ X :INPUT Value will be used but not modified.
+
+ :OUTPUT Input value not used (but some value must be given),
+ a value is returned as one of the values lisp
+ function NAME. Similar to the :IN-OUT style
+ of DEF-ALIEN-ROUTINE.
+ :INPUT-OUTPUT Input value may be used, a value is returned
+ as one of the values from the lisp function
+ NAME.
+
+ ** Note: In all 3 cases above the input VARIABLE will not be destroyed
+ or modified directly, a copy is taken and a pointer of that
+ copy is passed to the (presumably Fortran) external routine.
+
+ (OR (* X) :INPUT Array entries are used but not modified.
+ :STRING) :OUTPUT Array entries need not be initialized on input,
+ but will be *modified*. In addition, the array
+ will be returned via the Lisp command VALUES
+ from the lisp function NAME.
+
+ :INPUT-OUTPUT Like :OUTPUT but initial values on entry may be used.
+
+ The keyword :WORKSPACE is a nickname for :INPUT. The
+ keywords :INPUT-OR-OUTPUT, :WORKSPACE-OUTPUT,
+ :WORKSPACE-OR-OUTPUT are nicknames for :OUTPUT.
+
+ This is complicated. Suggestions are encouraged to
+ interface a *functional language* to a *pass-by-reference
+ language*.
+
+ CALLBACKS
+
+ A callback here means a function (or subroutine) that is passed into the Fortran
+ routine which calls it as needed to compute something.
+
+ The syntax of :CALLBACK is similar to the DEF-FORTRAN-ROUTINE:
+
+ (name (:CALLBACK return-type
+ {arg-description}))
+
+ The RETURN-TYPE is the same as for DEF-FORTRAN-ROUTINE. The arg description is the
+ same syntax as list of parameter forms for DEF-FORTRAN-ROUTINE. However, if the type
+ is a pointer type (like (* :double-float)), then a required keyword option must be
+ specified:
+
+ (name (* type :size size) &optional style)
+
+ The size specifies the total length of the Fortran array. This array is treated as a
+ one dimentionsal vector and should be accessed using the function FV-REF, which is
+ analogous to AREF. The SIZE parameter can be any Lisp form and can refer to any of the
+ arguments to the Fortran routine.
+
+ For example, a fortran routine can have the callback
+
+ (def-fortran-routine foo :void
+ (m (* :integer) :input)
+ (fsub (:callback :void
+ (x :double-float :input)
+ (z (* :double-float :size (aref m 0)) :input)
+ (f (* :double-float :size (aref m 0)) :output)))))
+
+ This means that the arrays Z and F in FSUB have a dimension of (AREF M 0), the first
+ element of the vector M. The function FSUB can be written in Lisp as
+
+ (defun fsub (x z f)
+ (setf (fv-ref f 0) (* x x (fv-ref z 3))))
+
+ Further Notes:
+ ===============
+
+ Some Fortran routines use Fortran character strings in the
+ parameter list. The definition here is suitable for Solaris
+ where the Fortran character string is converted to a C-style null
+ terminated string, AND an extra hidden parameter that is appended
+ to the parameter list to hold the length of the string.
+
+ If your Fortran does this differently, you'll have to change this
+ definition accordingly!
+
+ Call defcfun to define the foreign function.
+ Also creates a nice lisp helper function."
+ (multiple-value-bind (fortran-name name) (if (listp name-and-options)
+ (values (car name-and-options) (cadr name-and-options))
+ (values (make-fortran-name name-and-options) name-and-options))
+ (let* ((lisp-name (make-fortran-ffi-name `,name))
+ (hack-return-type `,return-type)
+ (hack-body `(,@body))
+ (hidden-var-name nil))
+ ;;
+ (multiple-value-bind (doc pars)
+ (parse-doc-&-parameters `(,@body))
+ (when (member hack-return-type '(:complex-single-float :complex-double-float))
+ ;; The return type is complex. Since this is a "structure",
+ ;; Fortran inserts a "hidden" first parameter before all
+ ;; others. This is used to store the resulting complex
+ ;; number. Then there is no "return" value, so set the return
+ ;; type to :void.
+ ;;
+ (setq hidden-var-name (gensym "HIDDEN-COMPLEX-RETURN-"))
+ (setq hack-body `(,@doc
+ (,hidden-var-name ,hack-return-type :output)
+ ,@pars))
+ (setq hack-return-type :void)))
+
+ `(progn
+ (cffi:defcfun (,fortran-name ,lisp-name) ,(%f77.get-return-type hack-return-type)
+ ,@(%f77.parse-fortran-parameters hack-body))
+ ,@(%f77.def-fortran-interface name hack-return-type hack-body hidden-var-name)))))
diff --git a/src/ffi/f77-mangling.lisp.in b/src/ffi/f77-mangling.lisp.in
index df051f0..a7cf0da 100644
--- a/src/ffi/f77-mangling.lisp.in
+++ b/src/ffi/f77-mangling.lisp.in
@@ -3,42 +3,42 @@
(in-package #:matlisp-ffi)
(eval-when (:compile-toplevel :load-toplevel :execute)
-(defconstant +f77-lower-case+ @F77_LOWER_CASE@
- "Fortran names are lower case if non-NIL")
-(defconstant +f77-underscore+ @F77_UNDERSCORE@
- "Fortran names have a trailing underscore if non-NIL")
-(defconstant +f77-extra-underscore+ @F77_EXTRA_UNDERSCORE@
- "Fortran names containing an underscore have an extra underscore appended if non-NIL")
-)
+ (defconstant +f77-lower-case+ @F77_LOWER_CASE@
+ "Fortran names are lower case if non-NIL")
+ (defconstant +f77-underscore+ @F77_UNDERSCORE@
+ "Fortran names have a trailing underscore if non-NIL")
+ (defconstant +f77-extra-underscore+ @F77_EXTRA_UNDERSCORE@
+ "Fortran names containing an underscore have an extra underscore appended if non-NIL")
-(defun %cat% (prefix-string s &optional suffix-string)
- (concatenate 'string
- prefix-string
- (string s)
- suffix-string))
+ (defun %cat% (prefix-string s &optional suffix-string)
+ (concatenate 'string
+ prefix-string
+ (string s)
+ suffix-string))
-(defun scat (prefix-string s &optional suffix-string)
- (intern (%cat% prefix-string s suffix-string)))
+ (defun scat (prefix-string s &optional suffix-string)
+ (intern (%cat% prefix-string s suffix-string)))
-;; If the Fortran function name is NAME, the Lisp FFI name prepends
-;; "FORTRAN-"
-(defun make-fortran-ffi-name (name)
- (scat "FORTRAN-" name))
+ ;; If the Fortran function name is NAME, the Lisp FFI name prepends
+ ;; "FORTRAN-"
+ (defun make-fortran-ffi-name (name)
+ (scat "FORTRAN-" name))
-(defun make-fortran-name (name)
- ;; Given the Fortran routine name NAME, this returns the real
- ;; underlying name. This depends on the compiler conventions being
- ;; used. Some Fortran compilers take the Fortran name NAME and
- ;; produce "name_" as the real routine name. Others will prepend
- ;; the underscore. Yet others might convert the name to all upper
- ;; case.
- (let* ((internal-underscore-p (position #\_ (symbol-name name)))
- (name (concatenate 'string
- (symbol-name name)
- (if +f77-underscore+ "_" "")
- (if (and +f77-extra-underscore+ internal-underscore-p)
- "_" ""))))
- (declare (ignorable internal-underscore-p))
- (if +f77-lower-case+
- (string-downcase name)
- name)))
+ (defun make-fortran-name (name)
+ ;; Given the Fortran routine name NAME, this returns the real
+ ;; underlying name. This depends on the compiler conventions being
+ ;; used. Some Fortran compilers take the Fortran name NAME and
+ ;; produce "name_" as the real routine name. Others will prepend
+ ;; the underscore. Yet others might convert the name to all upper
+ ;; case.
+ (let* ((internal-underscore-p (position #\_ (symbol-name name)))
+ (name (concatenate 'string
+ (symbol-name name)
+ (if +f77-underscore+ "_" "")
+ (if (and +f77-extra-underscore+ internal-underscore-p)
+ "_" ""))))
+ (declare (ignorable internal-underscore-p))
+ (if +f77-lower-case+
+ (string-downcase name)
+ name)))
+)
diff --git a/src/ffi/ffi-cffi.lisp b/src/ffi/ffi-cffi.lisp
index 8429984..5698605 100644
--- a/src/ffi/ffi-cffi.lisp
+++ b/src/ffi/ffi-cffi.lisp
@@ -10,30 +10,31 @@
(in-package #:matlisp-ffi)
-(define-constant +ffi-styles+
- '(:input :input-reference :input-value
- :input-output :output :workspace-output
- :workspace))
-
-(define-constant +ffi-types+
- '(:single-float :double-float
- :complex-single-float :complex-double-float
- :integer :long
- :string :character
- :callback))
-
-(define-constant +ffi-array-types+
- '(:single-float :double-float
- :integer :long))
-
-;; Separte the body of code into documentation and parameter lists.
-(defun parse-doc-&-parameters (body &optional header footer)
- (if (stringp (first body))
- (values `(,(%cat% header (first body) footer)) (rest body))
- (values (if (or header footer)
- (%cat% header "" footer)
- nil)
- body)))
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (define-constant +ffi-styles+
+ '(:input :input-reference :input-value
+ :input-output :output :workspace-output
+ :workspace))
+
+ (define-constant +ffi-types+
+ '(:single-float :double-float
+ :complex-single-float :complex-double-float
+ :integer :long
+ :string :character
+ :callback))
+
+ (define-constant +ffi-array-types+
+ '(:single-float :double-float
+ :integer :long))
+
+ ;; Separte the body of code into documentation and parameter lists.
+ (defun parse-doc-&-parameters (body &optional header footer)
+ (if (stringp (first body))
+ (values `(,(%cat% header (first body) footer)) (rest body))
+ (values (if (or header footer)
+ (%cat% header "" footer)
+ nil)
+ body))))
;; Create objects on the heap and run some stuff.
(defmacro with-foreign-objects-heaped (declarations &rest body)
@@ -122,8 +123,8 @@
,@body))))
;; Increment the pointer.
-(defun inc-sap (sap type &optional (n 1))
-"
+(definline inc-sap (sap type &optional (n 1))
+ "
Increment the pointer address by one \"slot\"
depending on the type:
:double-float 8 bytes
@@ -131,12 +132,12 @@
:complex-double-float 8x2 bytes
:complex-single-float 4x2 bytes
"
- (cffi:inc-pointer sap
- (ecase type
- (:double-float (* n 8))
- (:single-float (* n 4))
- (:complex-double-float (* n 16))
- (:complex-single-float (* n 8)))))
+ (cffi:inc-pointer sap
+ (ecase type
+ (:double-float (* n 8))
+ (:single-float (* n 4))
+ (:complex-double-float (* n 16))
+ (:complex-single-float (* n 8)))))
(define-modify-macro incf-sap (type &optional (n 1)) inc-sap)
diff --git a/src/utilities/functions.lisp b/src/utilities/functions.lisp
index c0570e8..079c6ba 100644
--- a/src/utilities/functions.lisp
+++ b/src/utilities/functions.lisp
@@ ...
[truncated message content] |