From: Jonathan
Subject: Interfacing to C code
Date: 
Message-ID: <u5sSOTS8c8q9qqBdaIGs+fKFfpqV@4ax.com>
Hi,

I am writing because I am trying to call a C function from Allegro
LISP and having difficulties regarding the parameters passed. In
particular, I want to a lisp variable to store a c structure after a
function call. I figured the easiest way to do this was to have lisp
pass a void * that gets filled by the c function (since the c struct
is actually really big and ugly). I cannot seem to get this to work at
all, so I have tried a simpler example shown here:

/* test.c */
#include <stdio.h>

void test ( int * pint ) {
	printf( "passed address: %lu\n", pint);
}


;; test.cl
;; Load the shared library
(cl:load "test.so")
(ff:def-foreign-call test ((pint (* :int))) :returning :void)
;; This is arbitrary since I am testing the address, not the value.
(defparameter test-par 15)
;; but...
(test test-par)


Evaluating this file yields:

USER(6): (test test-par)
passed:address: 15
8
USER(7):


And I don't understand why. Basically, lisp is sending the value of
the variable instead of the address. Shouldn't it know from the
definition that the C func wants the address and not the value?

Thanks in advance,
Jonathan
···@scorekeep.com

From: Erik Naggum
Subject: Re: Interfacing to C code
Date: 
Message-ID: <3166512264635721@naggum.no>
* Jonathan <··@spam.com>
| Shouldn't it know from the definition that the C func wants the
| address and not the value?

  No.  Lisp function calls evaluate all arguments in order, then call
  the function with the values so evaluated.  However, most values are
  actually pointers to boxes -- integers are sort of a special case.
  Try passing a cons cell.  If you pre-allocate a structure to fill in
  with values, you don't need to affect the Lisp binding, but you need
  to know how Lisp stores its values.  This can be complicated.  If
  the values in that structure are only going to be used in the C
  world, you can allocate it there and return a magic value that the C
  world knows what means.  Should you need to access the values from
  the Lisp world, the FFI should be able to handle individual values
  automatically, while aggregates may need some extra work.
  
#:Erik
From: Jonathan
Subject: Re: Interfacing to C code
Date: 
Message-ID: <YfwSOXa7GMFpIODIYVgDkVl2naOm@4ax.com>
Erik,

Thank you for this insight. Everything is working terrific now!

-Jonathan


On 05 May 2000 10:44:24 +0000, Erik Naggum <····@naggum.no> wrote:

>* Jonathan <··@spam.com>
>| Shouldn't it know from the definition that the C func wants the
>| address and not the value?
>
>  No.  Lisp function calls evaluate all arguments in order, then call
>  the function with the values so evaluated.  However, most values are
>  actually pointers to boxes -- integers are sort of a special case.
>  Try passing a cons cell.  If you pre-allocate a structure to fill in
>  with values, you don't need to affect the Lisp binding, but you need
>  to know how Lisp stores its values.  This can be complicated.  If
>  the values in that structure are only going to be used in the C
>  world, you can allocate it there and return a magic value that the C
>  world knows what means.  Should you need to access the values from
>  the Lisp world, the FFI should be able to handle individual values
>  automatically, while aggregates may need some extra work.
>  
>#:Erik
From: Joe Marshall
Subject: Re: Interfacing to C code
Date: 
Message-ID: <uitwswnd9.fsf@alum.mit.edu>
Jonathan <··@spam.com> writes:

> Hi,
> 
> I am writing because I am trying to call a C function from Allegro
> LISP and having difficulties regarding the parameters passed. In
> particular, I want to a lisp variable to store a c structure after a
> function call. I figured the easiest way to do this was to have lisp
> pass a void * that gets filled by the c function (since the c struct
> is actually really big and ugly). I cannot seem to get this to work at
> all, so I have tried a simpler example shown here:
> 
> /* test.c */
> #include <stdio.h>
> 
> void test ( int * pint ) {
> 	printf( "passed address: %lu\n", pint);
> }
> 
> 
> ;; test.cl
> ;; Load the shared library
> (cl:load "test.so")
> (ff:def-foreign-call test ((pint (* :int))) :returning :void)
> ;; This is arbitrary since I am testing the address, not the value.
> (defparameter test-par 15)
> ;; but...
> (test test-par)

You are passing the literal integer 15, you want to pass a pointer to an 
int.  Since you don't have an int handy, you can allocate one on the C 
stack:

(ff:with-stack-object (the-integer :int)        ; allocate a C integer on the stack
  (test the-integer)                            ; pass it to test
  (ff:fslot-value-typed :int nil the-integer))  ; suck out the value
From: dave linenberg
Subject: More Allegro C Interfacing Problems (Re: Interfacing to C code)
Date: 
Message-ID: <3915AEC0.9289A5CF@home.com>
Jonathan wrote:

> Hi,
>
> I am writing because I am trying to call a C function from Allegro
> LISP and having difficulties regarding the parameters passed.

I, too, am having problems with Allegro's Foreign Function Interface.

I am simply trying to repeat the example in the Allegro
foreign_functions.htm, section 5.5 entitled "Another example using arrays
to pass values".

I am using the Allegro Common Lisp linux trial version 5.01, which should
work.

The C code presented is simple:

int myreverse(n, x)
double *x; /* pointer to array of doubles */
int n; /* array length */
{
   int i;
    double d;
    for (i=0; i <= n/2; i++) {
        d = x[i];
        x[i] = x[n-1-i];
        x[n-1-i] = d;
    }
    return n;
}

After compiling the function and storing it into a library (.so) file,
the _documentation_  shows the following:
USER(40): (ff:def-foreign-call myreverse (fixnum (array double-float)))
t

but, my lisp comes back with.....

USER(66) (ff:def-foreign-call myreverse (fixnum (array double-float)))
Error: don't know how to convert type: DOUBLE-FLOAT
  [condition type: SIMPLE-ERROR]


So, I tried being more specific by doing the following:

USER(67): (ff:def-foreign-call myreverse (fixnum (array  (:array :double
3) double-float)))
MYREVERSE

which works.  Then, continuing, I make an array of double-floats in
lisp.....
USER(68): (setq x (make-array 3
                     :element-type `double-float
                     :initial-contents `(1.0d0
                                         2.0d0
                                         3.0d0)))

#(1.0d0 2.0d0 3.0d0)

But now, when I call the function from lisp, I get..
 [1] USER(69): (myreverse 3 x )
Error: `#(1.0d0 2.0d0 3.0d0)' is not of the expected type `DOUBLE-FLOAT'
  [condition type: TYPE-ERROR]

Can anybody show me how to get the example in the documentation to work?
Other examples do not work as well.  Is the documentation wrong, or am I
doing something wrong?  Thanks, in advance!!

Dave Linenberg
From: dave linenberg
Subject: Re: More Allegro C Interfacing Problems (Re: Interfacing to C code)
Date: 
Message-ID: <39162963.4622AF32@home.com>
Well, I finally managed to get the above example to work using  any of

USER(35): (ff:def-foreign-call myreverse (fixnum (in-array (:array :double)
(array double-float))))
MYREVERSE

or...
(ff:def-foreign-call myreverse (fixnum (in-array (:array :double)
(simple-array double-float (*)))))
(ff:def-foreign-call myreverse (fixnum (in-array (:array :double)
(simple-array double-float ))))

 USER(39): x
#(1.0d0 2.0d0 3.0d0)

 USER(40): (myreverse 3 x)
3

 USER(41): x
#(3.0d0 2.0d0 1.0d0)

But, it still seems the documentation is wrong, as well as scattered. I
needed to hop from implementation.htm
to foreign_functions.htm to ftype.htm to def-foreign-type.htm just to get an
idea of what to do successfully.  I still don't know which of any of the
above solutions *is* entirely proper.

I would gladly pay 100 bucks just to get a real, bound, hardcopy of the
documentation as well!!   If anybody has any useful suggestions or examples
of foreign function ( C ) to ACL, please comment.

Thanks,
Dave Linenberg