Allegro CL's Foreign Function Interface 
Author Message
 Allegro CL's Foreign Function Interface

Hello,
I have a question having to do with the Allegro CL's (version 6.0)
Foreign Function Interface. I defined a 'C' function as follows:
char *tststring(char *s);

I compiled the code and made a shared library out of it (I'm on a Linux
system).  Then in lisp I loaded it with:
(load "libtststring.so")

And then using the Foreign Function interface I created my lisp function
for calling it as follows:

(ff:def-foreign-call (tst-string "tststring") ((s (* :char) string))
  :returning ((* :char) string))

Now the string that is returned to me by my function call is correct but
the string that is being passed into my 'C' function is not. When I
enter the 'C' function I am only seeing the first character of the
string I am trying to pass to it ( I have confirmed this by having
included some debugging code).  I tried to redefine my lisp function as
follows but still with out success:

(ff:def-foreign-call (tst-string "tststring") ((s (* :char)
with-native-string)) ;; doesn't work either!
  :returning ((* :char) string))

Can someone give me some insight as to what I am doing wrong?
Many thanks!
Dave Richards



Fri, 15 Aug 2003 02:23:37 GMT  
 Allegro CL's Foreign Function Interface

| (ff:def-foreign-call (tst-string "tststring") ((s (* :char) string))
|   :returning ((* :char) string))
|
| Now the string that is returned to me by my function call is correct but
| the string that is being passed into my 'C' function is not. When I
| enter the 'C' function I am only seeing the first character of the
| string I am trying to pass to it ( I have confirmed this by having
| included some debugging code).  

this works for me:

(ff:def-foreign-call foo ((input (* :char)))
  :strings-convert t
  :returning ((* :char)))

--
Vebjorn

Shameless plug: Student looking for lispy summer job anywhere in the
United States.



Fri, 15 Aug 2003 05:03:16 GMT  
 Allegro CL's Foreign Function Interface
Thanks to Vebjorn Ljosa for the answer - I came up with something not so
dissimilar. And now, if you don't mind, how can I define a function that
expects an array of strings from a 'C' function. I tried the following
but with no success:

(ff:def-foreign-call (querry "sqlQuerry") ((s (* :char)))
   :returning (( *( * :char)) (simple-array simple-string(*) )))

I borrowed the syntax from the documentation that explains how to SEND
an array of strings to a 'C' function not how to retrieve one.  Any help
would be greatly appreciated!
Dave

Quote:


> | (ff:def-foreign-call (tst-string "tststring") ((s (* :char) string))
> |   :returning ((* :char) string))
> |
> | Now the string that is returned to me by my function call is correct but
> | the string that is being passed into my 'C' function is not. When I
> | enter the 'C' function I am only seeing the first character of the
> | string I am trying to pass to it ( I have confirmed this by having
> | included some debugging code).  

> this works for me:

> (ff:def-foreign-call foo ((input (* :char)))
>   :strings-convert t
>   :returning ((* :char)))



Sat, 16 Aug 2003 08:38:45 GMT  
 Allegro CL's Foreign Function Interface

| Thanks to Vebjorn Ljosa for the answer - I came up with something not so
| dissimilar. And now, if you don't mind, how can I define a function that
| expects an array of strings from a 'C' function. I tried the following
| but with no success:
|
| (ff:def-foreign-call (querry "sqlQuerry") ((s (* :char)))
|    :returning (( *( * :char)) (simple-array simple-string(*) )))

ACL does not automatically convert arrays of C strings to a Lisp type.
(at least it didn't in version 5, when I asked Franz, and I can't find
any mention of it in the ACL6 documentation.)

you can, however, tell FF:DEF-FOREIGN-CALL that you want the raw
address, and then dig out the strings yourself:

char **bar(void)
{
        char **strings;

        strings = calloc(4, sizeof(char *));
        if (!strings) return NULL;
        strings[0] = strdup("foo");
        if (!strings[0]) return NULL;
        strings[1] = strdup("bar");
        if (!strings[0]) return NULL;
        strings[2] = strdup("baz");
        if (!strings[0]) return NULL;
        return strings;

Quote:
}

(ff:def-foreign-call (bar-1 "bar") ()
  :returning ((* (* :char))))

(defun bar ()
  (let ((object (bar-1)))
    (when (zerop object)
      (error "C function bar() failed."))
    (loop
        for i from 0
        for pointer = (ff:fslot-value-typed '(:array (* :char)) :c object i)
        until (zerop pointer)
        collect (native-to-string pointer)
        do
          (ff:free-fobject pointer)
        finally
          (ff:free-fobject object))))

I'm not sure that it's OK to use FF:FREE-FOBJECT to free the memory
allocated dynamically by the C function, because the documentation
says only that FF:FREE-FOBJECT is for freeing object allocated by
FF:ALLOCATE-FOBJECT, but it "seems to work" (famous last words). :)

alternatively, you can write a C function for freeing the memory and
pass the pointer to it when you're done with the pointer on the Lisp
side.

--
Vebjorn



Sat, 16 Aug 2003 13:18:44 GMT  
 Allegro CL's Foreign Function Interface
Thanks so much for this info - It's helped tremendously!
Dave
Quote:


> | Thanks to Vebjorn Ljosa for the answer - I came up with something not so
> | dissimilar. And now, if you don't mind, how can I define a function that
> | expects an array of strings from a 'C' function. I tried the following
> | but with no success:
> |
> | (ff:def-foreign-call (querry "sqlQuerry") ((s (* :char)))
> |    :returning (( *( * :char)) (simple-array simple-string(*) )))

> ACL does not automatically convert arrays of C strings to a Lisp type.
> (at least it didn't in version 5, when I asked Franz, and I can't find
> any mention of it in the ACL6 documentation.)

> you can, however, tell FF:DEF-FOREIGN-CALL that you want the raw
> address, and then dig out the strings yourself:

> char **bar(void)
> {
>         char **strings;

>         strings = calloc(4, sizeof(char *));
>         if (!strings) return NULL;
>         strings[0] = strdup("foo");
>         if (!strings[0]) return NULL;
>         strings[1] = strdup("bar");
>         if (!strings[0]) return NULL;
>         strings[2] = strdup("baz");
>         if (!strings[0]) return NULL;
>         return strings;
> }

> (ff:def-foreign-call (bar-1 "bar") ()
>   :returning ((* (* :char))))

> (defun bar ()
>   (let ((object (bar-1)))
>     (when (zerop object)
>       (error "C function bar() failed."))
>     (loop
>    for i from 0
>    for pointer = (ff:fslot-value-typed '(:array (* :char)) :c object i)
>    until (zerop pointer)
>    collect (native-to-string pointer)
>    do
>      (ff:free-fobject pointer)
>    finally
>      (ff:free-fobject object))))

> I'm not sure that it's OK to use FF:FREE-FOBJECT to free the memory
> allocated dynamically by the C function, because the documentation
> says only that FF:FREE-FOBJECT is for freeing object allocated by
> FF:ALLOCATE-FOBJECT, but it "seems to work" (famous last words). :)

> alternatively, you can write a C function for freeing the memory and
> pass the pointer to it when you're done with the pointer on the Lisp
> side.



Tue, 19 Aug 2003 10:08:34 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. Foreign function interfaces of Allegro CL and Lucid CL

2. Allegro CL foreign function interface

3. Q:Foreign function interface for Allegro CL

4. Allegro CL Foreign Functions

5. Problems with Allecro CL Foreign Function interface/unsigned values

6. CL standard for foreign function interface

7. Clean's foreign function interface

8. Lucid's foreign function call interface

9. Announcement: operating system interface patch for Allegro CL 6.2

10. Allegro CL + Emacs Interface.

11. Allegro CL for Windows interface to Oracle?

12. interfacing Allegro CL with C++

 

 
Powered by phpBB® Forum Software