[Openmcl-devel] def-foreign-type problem
Gary Byers
gb at clozure.com
Sun Sep 22 18:35:04 PDT 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)
<field-defs>))
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))
NIL
2) Get your hands on the type description that was just created:
? (ccl::parse-foreign-type '(:struct :tst))
#<FOREIGN-RECORD-TYPE (STRUCT :TST) #x5238B66>
3) Give that type an "alternate alignment" of 16 bits:
? (setf (ccl::foreign-record-type-alt-align *) 16)
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)))
NIL
5) Is :f2 16 bits into the structure ?
? (macroexpand '(pref x :tst.f2))
(%GET-SIGNED-LONG X (/ 16 8))
T
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)))
NIL
3) Change the alignment of the newly-define structure:
? (realign-foreign-record-type :tst2 16)
#<FOREIGN-RECORD-TYPE (STRUCT :TST2 (:F1 (SIGNED 16)) (:F2 (SIGNED 32))) #x523FF4E>
4) Is :f2 16 bits into the structure ?
? (macroexpand '(pref x :tst2.f2))
(%GET-SIGNED-LONG X (/ 16 8))
T
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
http://clozure.com/cgi-bin/mailman/listinfo/openmcl-devel
More information about the Openmcl-devel
mailing list