[Openmcl-devel] FFI with functions that return (pointers to) structures

Anders Conradi beque at telia.com
Mon Feb 21 09:58:18 UTC 2005


On måndag, feb 21, 2005, at 10:29 Europe/Stockholm, Jeremy O'Donoghue 
wrote:

> I'm a relative CL-newbie (but many years of C/C++), so apologies for a
> possibly obvious question. I'm having trouble using the FFI with
> functions returning pointers to C structures, and it seems like the
> (rapidly improving) OpenMCL documentation doesn't quite cover this in
> detail.
>
> As a (short) example, I'm trying to put the return value of the
> syscall gtgrgid() into a class, for easier interaction with lisp
> functions.
>
> The C signature is: struct group *getgrgid(gid_t gid);
>
> struct group {
>   char *gr_name;
>   char *gr_passwd;
>   gid_t gid;
>   char **gr_mem;
> };
>
> In CL I have:
>
> (defclass sys_group ()
>   ((name :accessor name)
>    (gid :accessor gid :initarg :gid
> 	:initform (error "Require gid to initialize"))
>    (members :accessor members)))
>
> (defmethod initialize-instance :after ((group sys_group) &key)
>   (rlet ((pgroup :group))
>    (progn
>       (#_getgrgid pgroup (slot-value group 'gid)))))
> 	  (when pgroup
> 	  (setf (slot-value group 'name)
> 		(%str-from-ptr (pref pgroup :group.gr_name))))
> 	  (with-string-vector
> 	      (setf (slot-value group 'members)
> 		    (%str-from-ptr (pref pgroup :group.gr_mem))))))
>
> The extra parameter pgroup to #_getgrgid is based on the information
> in section 9.2.2 of the documentation says that I need to pass a first
> parameter of type 'pointer to returned struct/union' to foreign
> functions returning struct/union.

This only applies if your foreign function returns a structure. In your 
case the foreign function returns a pointer to a structure, and that is 
returned as a normal value an presented to your code as a mac-ptr.
What I think should work is to instead write

(defmethod initialize-instance :after ((group sys_group) &key)
   (let ((pgroup (#_getgrgid (slot-value group 'gid))))
    (progn
      (when pgroup
        (setf (slot-value group 'name)
              (%str-from-ptr (pref pgroup :group.gr_name))))
      (with-string-vector
          (setf (slot-value group 'members)
                (%str-from-ptr (pref pgroup :group.gr_mem)))))))

This is untested and I don't know what with-string-vector does, but the 
part about initializing pgroup in the let as the result of #_getgrgid 
instead of passing it as an extra argument to #_getgrgid is the 
important part.

>
> The code above fails at the call to #_getgrgid with an indication that
> the number of parameters is incorrect (don't recall the precise
> message, and I'm not sitting at my Mac now...)
> Everything following the call to #_getgrgid() is probably incorrect,
> but I've never gotten as far as returning from the call to test it.
>
> Thanks for any pointers you could give.
>
> Jeremy O'Donoghue
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>





More information about the Openmcl-devel mailing list