[Openmcl-devel] Foreign function calls

Gary Byers gb at clozure.com
Thu Jul 1 02:21:57 PDT 2004



On Thu, 1 Jul 2004, Andrew P. Lentvorski, Jr. wrote:

> Can anybody point me at some examples for the foreign function
> interface?
>
> What I'm trying to do is to call a C function with a signature of
>
> void gtk_init(int *argv, char **argc);

It's usually the other way around: "argc" is conventionally an integer
argument count (or a pointer to one) and argv is a pointer to one or
more "pointers to char" (C strings).

>
> I can open the library and dereference the function.  After going over
> the both the new and old docs, I can't figure out how to convert the
> OpenMCL fixnum into a C integer and then take the reference of it in
> order to pass its pointer into the function.
>

RLET can be used to create temporary "dynamic-extent" pointers to foreign
objects.

(rlet ((var typeI)) &body body)

executes BODY in an environment in which each VAR is bound to a temporary
(stack-allocated) pointer to an instance of the corresponding foreign type.

In

(rlet ((foo :int))
  ...)

FOO is a pointer to a C "int" (which happens not to have a
well-defined initial value).  The effect of this is something like
that of the C code fragment:

int _foo, *foo = &_foo;

with one important difference being that the int that the lisp code points
to isn't named.

(rlet ((foo :int 1))
  ...)

is similar, only the integer value that FOO points to is initialized to
1 in this case.


> I also don't see how to allocate the strings so that I can dereference
> it twice.

(WITH-CSTRS ((c-string-ptr lisp-string-expression)*) ...)

has the effect of copying the characters in the lisp string to a null-
terminated, stack-allocated block of memory and binding  the corresponding
c-string-ptr to a pointer to that block of memory; "c-string-ptr" is
effectively equivalent to a C "char *" pointer. If you want a pointer to
that pointer (a char **), you basically have to put the char * someplace:

(with-cstrs ((arg "Hello"))
  (rlet ((argv (:* (:* :char)) char-star))
    ...))

has the effect of binding ARGV to a pointer to a pointer to a null-terminated
sequence of characters.

For no particularly good reason, PREF (and (SETF PREF)) don't offer
convenient syntax for dealing with foreign arrays, and it's often
necessary to use lower-level primitives and do address arithmetic by
hand.  (Having a macro expand into code that does that address
arithmetic for you isn't rocket science, but it's never been
implemented in OpenMCL.)  Functions that take a "pointer to pointer to
char" argument (like #_gtk_init and #_main and the #_exec functions)
often expect that pointer to point to a null-terminated sequence of
character pointers.  There's a fairly scary-looking function in the
OpenMCL sources called CCL::CALL-WITH-STRING-VECTOR; it's used to
create an "argv"-like foreign vector from a set of lisp strings, and
is used in the guts of RUN-PROGRAM and (IIRC) to call #_gtk_init in
some of the (old) Linux gtk+ examples in the "ccl:examples;"
directory.

>
> Thanks for any help.
>
> -a
>
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>
>



More information about the Openmcl-devel mailing list