From: Tamas
Subject: advice about foreign function interfaces
Date: 
Message-ID: <1176932121.995054.150530@p77g2000hsh.googlegroups.com>
Hi,

I find that I need to call some Fortran (and occasionally C) code from
my Lisp programs (mostly linear algebra and other numerical code).  If
I understand correctly, most Lisp implementations have foreign
("alien" in CMUCL which I am using) interfaces which are not
compatible with each other, then there is CFFI and UFFI.  What's the
difference between the two?  Which one should I learn?

All I need is passing the pointer to the data in a simple array to
these functions (sys:vector-sap in CMUCL), but I don't want to be tied
to a single implementation if I don't have to be.

Thanks,

Tamas

From: Ken Tilton
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <kvxVh.480$ru1.204@newsfe12.lga>
Tamas wrote:
> Hi,
> 
> I find that I need to call some Fortran (and occasionally C) code from
> my Lisp programs (mostly linear algebra and other numerical code).  If
> I understand correctly, most Lisp implementations have foreign
> ("alien" in CMUCL which I am using) interfaces which are not
> compatible with each other, then there is CFFI and UFFI.  What's the
> difference between the two?

Both good. CFFI more portable and de facto CL standard now for those 
wanting portable code. So if you should ask me...

>  Which one should I learn?

... I would say CFFI.

kt

-- 
http://www.theoryyalgebra.com/

"Algebra is the metaphysics of arithmetic." - John Ray

"As long as algebra is taught in school,
there will be prayer in school." - Cokie Roberts

"Stand firm in your refusal to remain conscious during algebra."
    - Fran Lebowitz

"I'm an algebra liar. I figure two good lies make a positive."
    - Tim Allen
From: Luís Oliveira
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <m1hcrdjn26.fsf@deadspam.com>
Tamas <······@gmail.com> writes:
> All I need is passing the pointer to the data in a simple array to
> these functions (sys:vector-sap in CMUCL), but I don't want to be tied
> to a single implementation if I don't have to be.

In CFFI, there is WITH-POINTER-TO-VECTOR-DATA which is not yet
documented or implemented in all backends.  Such vectors should be
created through MAKE-SHAREABLE-BYTE-VECTOR.  This API makes sure the
data won't be moved by the GC, which in CMUCL's case means that it'll
make use of SYS:WITHOUT-GCING.

HTH

-- 
Luís Oliveira
http://student.dei.uc.pt/~lmoliv/
From: Joerg Hoehle
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <u1wibyq6c.fsf@users.sourceforge.net>
·············@deadspam.com (=?utf-8?Q?Lu=C3=ADs?= Oliveira) writes:

> Tamas <······@gmail.com> writes:
> > All I need is passing the pointer to the data in a simple array to
> > these functions (sys:vector-sap in CMUCL), but I don't want to be tied
> > to a single implementation if I don't have to be.
> 
> In CFFI, there is WITH-POINTER-TO-VECTOR-DATA which is not yet
> documented or implemented in all backends.
Nor even implementable at all in any arbitrary implementation.

>  This API makes sure the data won't be moved by the GC, which in
> CMUCL's case means that it'll make use of SYS:WITHOUT-GCING.
Which is proof enough that this is a bad API to use.
An extremely bad API.

It's ok for tight inner loops, but certainly unsuitable for anything
that has the slightest chance of being called from a callback or any
arbitrary Lisp code.

What kind of data do you need a pointer to? There are likely other
solutions which do not involve bad, debatable and sometimes
unimplementable APIs.

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Tamas
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <1177374693.372478.108330@y80g2000hsf.googlegroups.com>
On Apr 23, 1:08 pm, Joerg Hoehle <······@users.sourceforge.net> wrote:
> ·············@deadspam.com (=?utf-8?Q?Lu=C3=ADs?= Oliveira) writes:
> > Tamas <······@gmail.com> writes:
> > > All I need is passing the pointer to the data in a simple array to
> > > these functions (sys:vector-sap in CMUCL), but I don't want to be tied
> > > to a single implementation if I don't have to be.
>
> > In CFFI, there is WITH-POINTER-TO-VECTOR-DATA which is not yet
> > documented or implemented in all backends.
>
> Nor even implementable at all in any arbitrary implementation.
>
> >  This API makes sure the data won't be moved by the GC, which in
> > CMUCL's case means that it'll make use of SYS:WITHOUT-GCING.
>
> Which is proof enough that this is a bad API to use.
> An extremely bad API.
>
> It's ok for tight inner loops, but certainly unsuitable for anything
> that has the slightest chance of being called from a callback or any
> arbitrary Lisp code.
>
> What kind of data do you need a pointer to? There are likely other
> solutions which do not involve bad, debatable and sometimes
> unimplementable APIs.
>
> Regards,
>         Jorg Hohle
> Telekom/T-Systems Technology Center

Hi Jorg,

Thanks for your comment.  I need it for matrix operations, namely
calling matrix multiplication and linear algebra (especially linear
solver) routines from Atlas.  I think I will experiment with the
implementation's foreign interface first, and then port to CFFI when
my code stabilizes (if I see the need, or it I think it might be
useful for others).

Which (free) Lisp environment would be the best for my purposes?
Which one is recommended for number crunching?  I am currently working
with CMUCL.  The CLISP webpage explicitly says that CLISP may not be
the best for this, but I could not find a discussion on which compiler
is most used for this.

Thanks,

Tamas
From: Joerg Hoehle
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <uk5vx3jg9.fsf@users.sourceforge.net>
Tamas <······@gmail.com> writes:

> Thanks for your comment.  I need it for matrix operations, namely
> calling matrix multiplication and linear algebra (especially linear
> solver) routines from Atlas.

> Which (free) Lisp environment would be the best for my purposes?
> Which one is recommended for number crunching?  I am currently working
> with CMUCL.

That is a perfect choice for number crunching in Lisp. AFAIK, its FFI
can also pass arrays of FLOAT or DOUBLE-FLOAT to foreign (Fortran?)
code.  Other may be more qualified to respond about their experience
with cmucl.

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Luís Oliveira
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <m17is2iq5i.fsf@deadspam.com>
Joerg Hoehle <······@users.sourceforge.net> writes:
>> In CFFI, there is WITH-POINTER-TO-VECTOR-DATA which is not yet
>> documented or implemented in all backends.
> Nor even implementable at all in any arbitrary implementation.

Well, it is implementable in all Lisps CFFI supports and it has been
designed and implemented by James with the following 4 aproaches in
mind:

  1. The array is allocated in a static area.  Lispworks and Allegro can
     do this.

  2. The array is pinned so that it's not moved by eventual GC runs.
     This is what SBCL does.

  3. GC is temporarily disabled.  CMUCL and OpenMCL do this.

  4. The array is copied out to foreign memory and then copied back in,
     possibly using the block memory interface.  (e.g., CLISP does it
     this way, though a bit inefficiently.)


>>  This API makes sure the data won't be moved by the GC, which in
>> CMUCL's case means that it'll make use of SYS:WITHOUT-GCING.
> Which is proof enough that this is a bad API to use.
> An extremely bad API.
[...]
> It's ok for tight inner loops, but certainly unsuitable for anything
> that has the slightest chance of being called from a callback or any
> arbitrary Lisp code.

Yes, approach #3 should be used with care.  Perhaps an option forcing
those implementations to fallback to approach #4 would be a good
compromise, I'm not sure.  It can be a useful API though.

-- 
Luís Oliveira
http://student.dei.uc.pt/~lmoliv/
From: Joerg Hoehle
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <uodl93jlj.fsf@users.sourceforge.net>
Luis, and with all respect to James,

I appreciate your work on CFFI.

·············@deadspam.com (=?utf-8?Q?Lu=C3=ADs?= Oliveira) writes:
> Joerg Hoehle <······@users.sourceforge.net> writes:
> >> In CFFI, there is WITH-POINTER-TO-VECTOR-DATA which is not yet
> >> documented or implemented in all backends.
> > Nor even implementable at all in any arbitrary implementation.
> Well, it is implementable in all Lisps CFFI supports

> with the following 4 aproaches in mind:
>   1. The array is allocated in a static area.
>   2. The array is pinned so that it's not moved by eventual GC runs.
> 
>   3. GC is temporarily disabled.  CMUCL and OpenMCL do this.
>
>   4. The array is copied out to foreign memory and then copied back in,
>      possibly using the block memory interface.  (e.g., CLISP does it
>      this way, though a bit inefficiently.)

The inefficiency is not in the way clisp does it, 4. is inherently
inefficient (see below).

Furthermore, 4. introduces observable behaviour that is different from
the cases 1. and 2. (i.e. depending on whether and at what time the
Lisp or the C side perform the update to the memory region.)  This can
randomly break code written with a true pointer to a Lisp vector in mind.

> > It's ok for tight inner loops, but certainly unsuitable for anything
> > that has the slightest chance of being called from a callback or any
> > arbitrary Lisp code.
> Yes, approach #3 should be used with care.  Perhaps an option forcing
> those implementations to fallback to approach #4 would be a good
> compromise, I'm not sure.


> It can be a useful API though.

Only when it can be implemented efficiently (i. e. case 1 and 2 above).
I'd rather *not* implement it in cases 3. and 4., and tell the CFFI
users to conditionalize code on #-/#+cffi-features:PINNABLE-LISP-VECTOR
(or not care about portability and keep playing with Allegro or Lispworks).

When an implementation backend uses 4., then
WITH-POINTER-TO-VECTOR-DATA produces less performant code that if it
had been done manually, because the former always makes two copies,
whereas the programmer typically faces situations where only one
direction matters.

So we are presented an API that people seeking for some performance
(or perhaps portable performance) might consider using, and in fact it
will deliver them worse performance thn expected.  Great API, indeed.

When an implementation uses 3. and people start using it with a body
than runs for a long time (e.g. some server or socket), their Lisp
might crash randomly because of inhibited GC.  Great API, again.


BTW, I just went to the online documentation.  I didn't find it
documented.  Maybe that's good.  However people finding it by looking
at the CFFI source then have no chance to even *know* of the problems
and restrictions of 3. and 4.  That's perhaps not a good idea.

So I repeat:

+ Don't use that API for anything but tight inner loops.
+ Better yet: library writers: conditionalize code: provide two
  implementations, with and without that API.
  (there had been some discussion about #+cffi-features:xyz)
+ Better yet: avoid that API, seek alternative designs.

+ Provide API for efficient memory block transfers.  That should
  eliminate the need for many uses of WITH-POINTER.
  (that API might use INHIBIT-GC internally).

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: David Lichteblau
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <slrnf377fr.d62.usenet-2006@babayaga.math.fu-berlin.de>
Hi,

On 2007-04-24, Lu�s Oliveira <·············@deadspam.com> wrote:
> Well, it is implementable in all Lisps CFFI supports and it has been
> designed and implemented by James with the following 4 aproaches in
> mind:
>
>   1. The array is allocated in a static area.  Lispworks and Allegro can
>      do this.
>
>   2. The array is pinned so that it's not moved by eventual GC runs.
>      This is what SBCL does.
>
>   3. GC is temporarily disabled.  CMUCL and OpenMCL do this.
>
>   4. The array is copied out to foreign memory and then copied back in,
>      possibly using the block memory interface.  (e.g., CLISP does it
>      this way, though a bit inefficiently.)

this API is probably useful in some situations, but having thought about
it a little more since asking about it on cffi-devel, I have come to
agree with Joerg Hoehle that it is too general for most uses and that
his proposed block copying mechanism is better for portable programs.


When I wanted to use this API, my code
  - accepted arbitrary arrays from user code
  - would block in FFI

Strategy (1) is not useful, because it requires the user to create
special arrays.  If I decided to use this API anyway, I would have to
allocate a temporary array to be compatible with (1).  But that means
unnecessary copying for implementations (2) and (4).  And the blocking
behaviour rules out implementation strategy (3) for any Lisp with
support for threads.


So the only portable mechanism is copying as described by Joerg, which
would be somewhat like (4), but with explicit control over which parts
to copy when.

Given that SBCL is probably the only implementation with nice support
for (2), I could (optionally) still put #+sbcl into my own code as an
alternative, highly optimized code path.  (Or, if there is ever another
Lisp with this feature, it could be #+cffi-features:with-pinned-object,
but in any case moderately fast and completely portable code could be
written without it.)


d.
From: fireblade
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <1176968602.329871.105910@q75g2000hsh.googlegroups.com>
Tamas íàïèøà:
> Hi,
>
> I find that I need to call some Fortran (and occasionally C) code from
> my Lisp programs (mostly linear algebra and other numerical code).  If
> I understand correctly, most Lisp implementations have foreign
> ("alien" in CMUCL which I am using) interfaces which are not
> compatible with each other, then there is CFFI and UFFI.  What's the
> difference between the two?  Which one should I learn?
>
> All I need is passing the pointer to the data in a simple array to
> these functions (sys:vector-sap in CMUCL), but I don't want to be tied
> to a single implementation if I don't have to be.
>
> Thanks,
>
> Tamas

CFFI  definately

bobi
From: Tamas
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <1176995231.476743.275490@e65g2000hsc.googlegroups.com>
On Apr 19, 3:43 am, fireblade <·················@gmail.com> wrote:
> Tamas íàïèøà:
>
>
>
> > Hi,
>
> > I find that I need to call some Fortran (and occasionally C) code from
> > my Lisp programs (mostly linear algebra and other numerical code).  If
> > I understand correctly, most Lisp implementations have foreign
> > ("alien" in CMUCL which I am using) interfaces which are not
> > compatible with each other, then there is CFFI and UFFI.  What's the
> > difference between the two?  Which one should I learn?
>
> > All I need is passing the pointer to the data in a simple array to
> > these functions (sys:vector-sap in CMUCL), but I don't want to be tied
> > to a single implementation if I don't have to be.
>
> > Thanks,
>
> > Tamas
>
> CFFI  definately
>
> bobi

Thanks for the suggestions.  I looked at the CFFI tutorial, but the
example with curl is a bit overwhelming at this point.  Could somebody
please give me hints on the steps to call a Fortran function "foo"
with arguments INTEGER :: n and DOUBLE PRECISION :: vec(n) that
resides in the library "foo.so"?  Then I would read the manual for the
functions you mention and I would have an idea on how it works.

Thanks,

Tamas
From: Lars Rune Nøstdal
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <462788a5$0$29071$c83e3ef6@nn1-read.tele2.net>
On Thu, 19 Apr 2007 08:07:11 -0700, Tamas wrote:

> call a Fortran function "foo" with arguments INTEGER :: n
> and DOUBLE PRECISION :: vec(n) 

either http://common-lisp.net/project/cffi/manual/html_node/foreign_002dfuncall.html
or http://common-lisp.net/project/cffi/manual/html_node/defcfun.html

> that resides in the library "foo.so"?  

http://common-lisp.net/project/cffi/manual/html_node/load_002dforeign_002dlibrary.html

-- 
Lars Rune Nøstdal
http://nostdal.org/
From: Tamas
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <1177008781.368392.46140@l77g2000hsb.googlegroups.com>
On Apr 19, 11:20 am, Lars Rune Nøstdal <···········@gmail.com> wrote:
> On Thu, 19 Apr 2007 08:07:11 -0700, Tamas wrote:
> > call a Fortran function "foo" with arguments INTEGER :: n
> > and DOUBLE PRECISION :: vec(n)
>
> eitherhttp://common-lisp.net/project/cffi/manual/html_node/foreign_002dfunc...
> orhttp://common-lisp.net/project/cffi/manual/html_node/defcfun.html
>
> > that resides in the library "foo.so"?
>
> http://common-lisp.net/project/cffi/manual/html_node/load_002dforeign...
>
> --
> Lars Rune Nøstdalhttp://nostdal.org/

Lars,

Thanks for the links, it is becoming clearer.  I still have a
question: Fortran only accepts pointers.  So what's the best way to
pass an integer? Write a C wrapper,
or make a one-element simple array and pass that, or is there
something else I missed?

Thanks,

Tamas
From: Thomas F. Burdick
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <1177056404.768701.136200@q75g2000hsh.googlegroups.com>
On Apr 19, 8:53 pm, Tamas <······@gmail.com> wrote:

> Thanks for the links, it is becoming clearer.  I still have a
> question: Fortran only accepts pointers.  So what's the best way to
> pass an integer? Write a C wrapper,
> or make a one-element simple array and pass that, or is there
> something else I missed?

I'd really recommend that you use your implementation's FFI
interface.  Alien is very nice, well documented and understood, you
will be able to ask for help from the implementors, and it's the best
way to get an idiomatic, efficient interface on CMUCL and SBCL.  If
you later find that you need portability, it shouldn't be too
difficult to port to CFFI -- or, if it is, that means that you used
features which CFFI did not make available, and thus saved yourself
some pain up front.

(exhale)

Using alien, you could stack allocate the space you need using with-
alien.  For example, to wrap a function %FOO which takes three int *
arguments, you could do it like:

(defun foo (x y z)
  (with-alien ((x int x)
	       (y int y)
	       (z int z))
    (%foo (addr x) (addr y) (addr z))))
From: ············@gmail.com
Subject: Re: advice about foreign function interfaces
Date: 
Message-ID: <1177096213.387872.50220@p77g2000hsh.googlegroups.com>
On Apr 19, 11:53 am, Tamas <······@gmail.com> wrote:
> Thanks for the links, it is becoming clearer.  I still have a
> question: Fortran only accepts pointers.  So what's the best way to
> pass an integer? Write a C wrapper,
> or make a one-element simple array and pass that, or is there
> something else I missed?

First you should find out the linking conventions of your Fortran
compiler -- how it represents strings, whether the linker prepends /
appends underscore(s) to function names, and the like.  Once you do
that, then you can call the Fortran function directly using the Lisp's
FFI.

The Matlisp project worked on a Fortran-specific FFI.  We may have
done something similar for lisp-matrix.  Ask me and I'll poke around
for you.

mfh