[Openmcl-devel] more openmcl foreign ptr access issues
Cyrus Harmon
ch-openmcl at bobobeach.com
Mon Sep 13 18:14:22 PDT 2004
Ok, I'm suitably scared. Now to consider other approaches and hopefully
find one that is less scary... I'm open to suggestions if anyone's got
any.
The (perhaps misguided) idea behind this whole thing was that one could
build some of the ffi machinery into some MOP machinery and be able to
get access to these facilities using a metaclass and some appropriate
initargs to the slot specs in the defclass. Of course it's proving to
be far more complex than I imagined when I started. The MOP stuff was
inspired by Kevin Rosenberg's use of MOP in clsql and seemed like a
good idea at the time. The FFI stuff was going swimmingly using the
interface database and the reader macros until I decided to put yet
another layer of indirection around all that stuff, at which point
things got messy in a hurry.
Thanks again,
Cyrus
On Sep 13, 2004, at 5:50 PM, Gary Byers wrote:
>
>
> On Mon, 13 Sep 2004, Cyrus Harmon wrote:
>
>> Ok, hot on the heels of figuring out how to get the MOP stuff to DWIM,
>> now I'm trying (unsuccessfully, of course) to get access to foreign
>> data using pref.
>>
>> Everything works fine if I do:
>>
>> (pref (foreign-ptr instance) :v<I>mage_<B>uffer.height))
>>
>> But if I try to do:
>>
>> (pref (foreign-ptr instance) (slot-definition-foreign-field slotd))
>>
>> (where the slot-def call is doing the right thing), I fail miserably.
>> This sounds like the allocate-record I had a couple weeks back and is
>> most likely a symptom of the same misunderstanding of how to properly
>> use the interface database. But, in any event, I still feel like this
>> is a reasonable thing to do. Anyway to have a call to pref determine
>> the field name at runtime or am I out of luck here?
>>
>> Thanks,
>>
>> Cyrus
>>
>
> PREF is a macro; it tries to generate a lisp form that, when compiled
> and executed, does some sort of memory access. Most of the work is
> currently done in a function called CCL::%FOREIGN-ACCESS-FORM. To
> allow for following a chain of field accessors (x.y.z),
> %FOREIGN-ACCESS-FORM, takes a BIT-OFFSET argument that gets incremented
> whenever a type is found to denote a record (struct/union) type and
> an accessor denotes a field in that record type.
>
> When it reaches a primitive type (or, more accurately, runs out of
> accessors ...), it asks the foreign type to produce a lisp form that
> can be used to access an instance of that foreign type, given the
> original (usually ...) first arg to PREF and the accumulated bit
> offset. (Using a bit offset here is supposed to enable access to
> bitfields which may not be byte-aligned.)
>
> The idiom that's used (stolen/borrowed/watered-down from CMUCL's
> ALIEN system) is
>
> (invoke-foreign-type-method :extract-gen type base-form bit-offset)
>
> In a simple case - something like
>
> (pref int-ptr :int)
>
> - where there are no record types or accessors involved - this devolves
> into asking the foreign INTEGER type how to access a signed integer
> of width 32 at bit-offset 0 from INT-PTR (or, more accurately, how
> to generate a form that will do so when compiled and executed). The
> expansion will be something like:
>
> (ccl:%get-signed-long INT-PTR (/ 0 8))
>
> and the compiler will generate a LOAD instruction (and possibly some
> hysterical boxing ...)
>
> There aren't that many primitive foreign types (signed and unsigned
> integers, two flavors of floats, pointers, not much else that I can
> think of.) You -could- write functions that were analogous to
> the primitive foreign type's :EXTRACT-GEN "methods":
>
> (defun dereference-integer-at-runtime (foreign-integer-type pointer
> bit-offset)
> (cond ((foreign-integer-type-signed foreign-integer-type)
> (case (foreign-type-bits foreign-integer-type)
> (8 (%get-signed-byte pointer (/ bit-offset 8)))
> (16 (%get-signed-word pointer (/ bit-offset 8)))
> ...))))
>
> and do the same for for FLOAT and POINTER types, and define a SETF
> function
> for each of the primitive types. That would work (at least in theory),
> but you'd be doing an amazing amount of type parsing to get at what's
> usually a LOAD or STORE instruction, every time that you wanted to
> access
> a slot in a foreign instance. Note that if we add up the number of
> actual primitive %get/%set functions that are involved in this, we'd
> probably find around 10 of each. Interpreting all of this type
> information
> at runtime to discover which of those 10 accessors or setters to use
> doesn't seem like much bang for the buck.
>
> I don't want to try to solve the problem for you, but I do want to try
> to scare you out of this approach, and to note that other solutions
> are possible. (There are existence proofs that other solutions are
> possible.)
More information about the Openmcl-devel
mailing list