[Openmcl-devel] FFI with functions that return (pointers to) structures
Anders Conradi
beque at telia.com
Mon Feb 21 01:58:18 PST 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