Subject: [clisp-list] FFI with complex numbers?

From: Michael Goffioul <[email-masked]>
Date: Thu May 6 08:51:39 2004

Hi, 
 
Is it possible to use complex numbers with FFI? What I want to do is to pass 
complex numbers from LISP to C code (whatever the format received by the C 
function), but I don't know if it's possible, and how to declare my FFI 
function's arguments (function would be located in a shared lib, and declared 
with def-call-out). My goal is to access BLAS and LAPACK fortran routines from 
LISP. I know there's MatLisp, but AFAIK it doesn't support CLISP. 
 
Thanks. 
Michael.

---

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Mon May 10 07:01:01 2004

Michael Goffioul wrote:

>The problem is that arrays are coming from LISP objects and processed 
>by underlying FORTRAN code, which usually modifies arrays in-situ. 
There's FFI :in-out for that (for fixed-size arrays only).
You can't still escape copying.

malloc + copy + call + copy back is little different from what
calling a foreign-call-out function would do (except for stack-allocation).

>the only problem is that macros like WITH-FOREIGN-OBJECT or 
>WITH-C-VAR only accept a single variable (at least that's how I 
>understood the doc). Aren't there equivalent for multiple variables? 

This was my initial idea, then I realized that it would make the supporting C code much more complex. Dealing with complexity should be done at the Lisp level, where it's easily expressible. Furthermore, with multiple variables comes the duality of let/let*, i.e. sequential or parallel evaluation. I wasn't going to write two forms.
What's wrong with either
o a nested with-foreign-object
o or a single with-foreign-object using a c-struct of two things?

>Up to now, I'm left with code like this:
It's ok. You have to resort to c-pointer, as my article explained.

"I'm left with" sounds to me like you're missing something?
I believe the code doesn't look much different from what you'd write using UFFI (not that I recommend the UFFI API, but CLISP doesn't offer a high-level API for variable arrays).

Minor points about your code:

o Either use ffi:allocate-deep instead of calling parse-c-type
or stay with foreign-allocate but justify this choice by using (LOAD-TIME-VALUE (parse-c-type 'int)). You'll get a little less computation upon each invocation.

o The code could easily be switched to with-foreign-object.
It will then feel more safe with automatic protection against memory leaks in case someone ^C in the middle.

I still haven't written macro-optimizers for the typical backquote-length case (that would suit your need):
(with-foreign-object (fa `(c-array int ,(length a)) body)
The goal of this optimization would be to eliminate some run-time PARSE-C-TYPE.
It would be the pendant of the :count option to allocate.
Sadly, the current FFI top-level WITH-* macros imply some run-time slow parse-c-type computations while FOREIGN-ALLOCATE with :count may not. Of course, malloc() has other speed implications...

Regards,
	Jorg Hohle.

---

From: "Goffioul Michael" <[email-masked]>
Date: Tue May 11 05:07:10 2004

> Hi,
> 
> Goffioul Michael wrote:
> >> [...] Matlisp does.  However,
> >> it does require your Lisp to have a specialized array with
> >> double-float elements that are arranged in one contiguous area,
> >I don't know(think) that direct memory mapping is possible in CLISP.
> >It uses copy to send/retrieve data to/from FFI functions.
> 
> The FFI is not the problem if you want to interface to some 
> foreign code. You can always write modules, which, as an 
> other article of mine explained, feature full access to Lisp 
> objects. One could build modules even --without-dynamic-ffi :-)
> but few people know about this, or maybe very few people 
> value this possibility.

Would you then be able to make an external C functions acces the
internal data of a LISP vector directly in "double*"-like way
(provided this is possible with the internal representation of
a vector in CLISP)?
Could you point me to some documentation about modules? I read the
CLISP implementation doc, but didn't find it very explicit regarding
modules.

> The problem IMHO is as follows:
> 
> Sam Steingold wrote:
> >You are right, CLISP does not have specialized float arrays.
> >It would be relatively easy to add them in the NO_TYPECODES model
> >(mostly used on 32-bit processors).
> 
> So you cannot have Matlist write the non-existant CLISP FP arrays :-)
> 
> The FFI is, by the nature of conversions, a slow interface 
> (it's an interpreter for a foreign-function description 
> language). Some modules
> could benefit from direct access to Lisp objects.
> So far, few people have come up with time measurements. 
> Modules where it's
> known to make a difference are regexp. Modules where it could make a
> difference are those where functions are either called very 
> often, or on
> large data.
> But still, I believe run-time invocations of parse-c-type 
> typically cost
> more than the FFI conversion overhead.
> Modules where it makes no difference are obviously those 
> where one function
> is called for a long computation.
> 
> BTW, do you except your function to be called with plenty of 
> different array sizes? Otherwise, typical memoization 
> techniques of the FOREIGN-FUNCTION object could be used: 
> you'd call a memoized specialisation of the foreign function 
> restricted to e.g. exactly (C-ARRAY int 100). That's the 
> fastest you could get with the FFI!

It's expected to be used as a library. So theoretically, the
array size can be anything. I don't think that memoization would
be the best solution.

Michael.