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)
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?
* Jonathan <n...@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.
>* Jonathan <n...@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.
> 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
> 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:
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!!
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.