[Openmcl-devel] def-foreign-type problem

Gary Byers gb at clozure.com
Mon Sep 23 01:35:04 UTC 2002

On Sun, 22 Sep 2002, John DeSoi wrote:

> Hi Gary,
> At 11:46 PM -0600 9/21/02, Gary Byers wrote:
> >That's as expected (and is equivalent to what you'd get if you compiled:
> >
> >struct {
> >   short f1;
> >   long f2;
> >};
> >
> >in C (under default alignment rules.)  It's also equivalent to:
> >
> >(ccl::def-foreign-type nil
> >                   (:struct tst-with-explicit-padding
> >                      (:f1 :short)
> >                      (:pad :short) ; ensure 32-bit alignment of the following
> >                      (:f2 :long)))
> I thought it might be something like this, but I also tested making a
> struct with 3 short values. The size of that is 6 bytes. Why not 8
> here, or is padding not an issue at the end of the structure?

The padding is to ensure that :f2 winds up at an address that's a multiple
of its size.

Padding at the end of a structure is relevant when the structure is
a component of another structure (it affects the alignment of subsequent
fields in the containing structure.)

> >
> >Out of curiosity, did you ask about this because you have some C code
> >that assumes 16-bit alignment, or were you just curious ?  (I'd sort
> >of convinced myself that there was no need to handle 16-bit alignment
> >in DEF-FOREIGN-TYPE, since that would only exist in a few old Apple
> >header files that the interface translator should process ...)
> >
> Yes, I have run into this as a possible problem in trying to solve
> the issue of getting a FSSpec to pass to a foreign library. With the
> pointers you gave me, I discovered the entry points FSPathMakeRef and
> FSGetCatalogInfo which turns a FSRef into a FSSpec (both were
> accessible without opening the core foundation library). I can call
> both routines without error, but the library fails to open or create
> the file. In looking at the name field of the FSSpec, it (finally)
> became obvious to me that it was off by 2 bytes. So if I want to read
> or write data from FSSpec struct, I need to load it's definition with
> (use-interface-dir :carbon) rather than defining it myself?

Yes, at present.  Sort of.

Loading a record (struct or union) type from the database goes through
something called CCL::%DETERMINE-RECORD-ATTRIBUTES to assign offsets
and sizes to the record's fields; DEF-FOREIGN-TYPE just loops over the
fields, using the "natural" (= easiest on the hardware = like the rest
of the world) alignment of each field, while
%DETERMINE-RECORD-ATTRIBUTES takes an optional argument that specifies
an alternate alignment.

Unless and until DEF-FOREIGN-TYPE lets you say something like:

  (def-foreign-type nil (:struct (:<FSS>pec :alt-align 16)

you seem to have a few options:

 a) use the interface translator/database.

 b) Tell the foreign type system that the structure type has an
    "alternate alignment", before defining its fields:

   1) Let the type system know that :test is a :struct type:

? (ccl::def-foreign-type nil (:struct :tst))

   2) Get your hands on the type description that was just created:
? (ccl::parse-foreign-type '(:struct :tst))

   3) Give that type an "alternate alignment" of 16 bits:
? (setf (ccl::foreign-record-type-alt-align *) 16)

   4) Define the record's fields.  (Ask the PPC to forgive you.  Blame Apple.)

? (def-foreign-type nil (:struct :tst
			       (:f1 :short)
			       (:f2 :long)))

   5) Is :f2 16 bits into the structure ?

? (macroexpand '(pref x :tst.f2))
(%GET-SIGNED-LONG X (/ 16 8))

 c) Fixup a record type (to have a new, possibly null, alternate alignment)
 after it has been defined.

   1) Define a function to do so:

? (defun realign-foreign-record-type (rtype-name &optional (alt-align 16))
    (let* ((rtype (or (ccl::info-foreign-type-struct rtype-name)
	     	      (ccl::info-foreign-type-union rtype-name))))
      (if (null rtype)
        (error  "No known foreign record type named ~s" rtype-name))
      (let* ((fields (ccl::foreign-record-type-fields rtype)))
        (ccl::%determine-record-attributes rtype fields alt-align))))

   2) Define a record type and its fields:

? (def-foreign-type nil (:struct :tst2
			       (:f1 :short)
			       (:f2 :long)))

   3) Change the alignment of the newly-define structure:

? (realign-foreign-record-type :tst2 16)

   4) Is :f2 16 bits into the structure ?

? (macroexpand '(pref x :tst2.f2))
(%GET-SIGNED-LONG X (/ 16 8))

Of those options, (a) looks easiest to me, but it's pretty clear that there
needs to be some supported way of doing this procedurally as well.

> Thanks again for all your help,
> John DeSoi, Ph.D.

Openmcl-devel mailing list
Openmcl-devel at clozure.com

More information about the Openmcl-devel mailing list