[Openmcl-devel] FFI help...get address to element in structure

Gary Byers gb at clozure.com
Mon Sep 21 14:55:42 UTC 2009

On Sun, 20 Sep 2009, Michael Kohout wrote:

> Thanks for the tips, guys.  I've got one more (really trivial) problem:
>  I've got a small dylib to paper over FFI issues with some c macros I
> need: FD_ZERO, FD_ISSET and family.
> Anyways-I load the dylib:
> (open-shared-library "/Users/development/Documents/networkServer/build/R
> elease/libnetworkServer.dylib")
> and I can call the function when I use external-call directly:
> (defparameter *fd-set* (ccl::make-gcable-record fd_set))
> (external-call "mike_fd_zero" (:* (:STRUCT :FD_SET)) *fd-set* :void)
> but when I load the interface directory I've set up, it doesn't find the
> method:
> (use-interface-dir :network-helper )
> #<INTERFACE-DIR :NETWORK-HELPER #P"network-helper/" #x3000416D290D>
> CL-USER> #_?mike_fd_zero

That's saying that it can't find a function declaration for mike_fd_zero
in the interfaces.  EXTERNAL-CALL can find the address of a function with
that name in the set of opened shared libraries

> Does the dylib have to be in a certain place for the runtime to pick it
> up or something?  Am I missing a simple step?  Could I be messing
> something up when generating the ffi/cdb files?  Here's the meat of my
> populate.sh file:
> CFLAGS="-m64 -fobjc-abi-version=1 -Wno-endif-labels
> -mmacosx-version-min=10.4.8";export CFLAGS
> /Users/development/Applications/ffigen4/bin/h-to-ffi.sh/Users/development/Applications/ccl-head/darwin-x86-headers64/network-he
> lper/C/interface.h 

That would have produced a .ffi file, assuming that there's some whitespace
between the name of the shell script and the name of the .h file.  The .ffi
file contains roughly the same information as the .h file does, but it's
in a lisp-like syntax that's easier to parse from lisp than the .h file
would be.

You then need to run a lisp function to parse the (one or more) .ffi
files in a given interface directory into a set of .cdb files:

? (require "PARSE-FFI")

? (ccl::parse-standard-ffi-files :network-helper)

It's generally necessary to call CCL::PARSE-STANDARD-FFI-FILES twice (for
fairly obscure reasons having to do with forward-referenced constant

You can generate the .ffi file and parse the result into .cdb files in
one step by doing:

? (create-interfaces :network-helper)

I don't know if the .cdb files were just missing (or empty) or not,
but they don't seem to contain the declaration you're trying to use.

> FYI I'm running this on the x86_64 build of CCL.

There are five such builds in the current release and another 5 in
the trunk ...

> Anyways, thanks for the help so far!
> Mike Kohout
> On Sat, Sep 19, 2009 at 2:01 AM, Gary Byers <gb at clozure.com> wrote:
>       Two unrelated points (maybe three.  Hmm.  Some of them may be
>       related.
>       Ahem.)
>       Some points:
>       - If a structure has a non-scalar field (e.g., an
>       array/strucure/union),
>        then
>        (pref ptr :struct_type.non_scalar_field_name)
>        returns a pointer to that field; if the field is scalar,
>       then PREF returns
>        its value.
>        It doesn't make sense to talk about the value of a
>       non-scalar, but it
>        does make sense to talk about either the value or address of
>       a scalar.
>        As Matt notes, there's nothing in CCL's FFI that does that
>       for you,
>        but something like:
>        (field-address pointer accessor) ; syntax like (PREF pointer
>       accessor)
>        would be useful and easy to implement (as long as the field
>       in question
>        was byte-addressable - it's hard to talk about the address
>       of a bitfield.)
>       - a signal mask is usually of type "sigset_t"; what a
>       "sigset_t" is is
>        platform-dependent (it's sometimes just a 32-bit integer,
>       other times
>        a small array of integers or bytes.  Depending on whether
>       "sigset_t"
>        is a scalar or aggregate type, PREF might already be doing
>       the right
>        thing.
>       - it'd take a while to explain what the issues are (they're
>       mostly related
>        to the GC), but there isn't really any support for
>       user-defined signal
>        handlers in CCL.  (If/when there is, you'd basically have to
>       use that
>        support rather than calling "sigaction" yourself.)
>        Until that support exists ... well, I was going to say that
>       you might
>        be able to get away with a very simple handler that ran with
>       all signals
>        masked, but I'm not even sure if that handler would be able
>       to cons
>        safely.
>        The constraints in this case don't have to do with the FFI,
>       but with
>        threads, the GC, and the way that they interact.
> On Sat, 19 Sep 2009, R. Matthew Emerson wrote:
> On Sep 18, 2009, at 6:24 PM, Michael Kohout wrote:
>       Next week I'm doing a presentation to my local
>       lisp user group on FFI
>       (CFFI and CCL's FFI).  My example is a simple
>       network client and
>       server.
>       Anyways, the code I'm writing requires me to get
>       the address to a
>       field in a struct( &sa.sa_mask, where sa is a
>       sigaction structure).
>       Does CCL's ffi system allow me to get this
>       without munging around
>       with the internal layout of the structure?  If
>       so, how?
> I don't know if this qualifies as munging around, but maybe
> this
> example will help.
> ;; struct sigaction sa;
> ;; (sort of;  in ccl, sa is a macptr referencing a
> stack-allocated
> structure)
> (rlet ((sa (:struct sigaction)))
>  ;; sa.sa_mask = 999;
>  (setf (pref sa :sigaction.sa_mask) 999)
>  ;; char *p = &sa.sa_mask
>  (with-macptrs ((p (%inc-ptr sa (ccl::get-field-
> offset :sigaction.sa_mask))))
>    ;; return *(long *)p;
>    (%get-long p)))
> If you don't really need a pointer to the sa_mask field and
> just want
> to know what its contents are (or to set them), you can use
> (pref
> sa :sigaction.sa_mask).
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel

More information about the Openmcl-devel mailing list