[Openmcl-devel] another make-record question
Gary Byers
gb at clozure.com
Fri Aug 20 09:16:02 PDT 2004
On Fri, 20 Aug 2004, Cyrus Harmon wrote:
>
> On Aug 20, 2004, at 3:50 AM, Gary Byers wrote:
>
> > MAKE-RECORD's a macro; it processes its first argument at macroexpand
> > time and expands any initialization forms in the macro call into
> > (SETF (PREF ...) ...) forms.
> >
> >
> > See <http://openmcl.clozure.com/Doc/re77.html>
> >
> > "Processing the first argument at macroexpand time" -could- be done by
> > a non-macro function at runtime, at least in theory. The processing
> > in question involves determining the size of the named foreign type or
> > record, and you -could- do that at runtime (and #_malloc and #_bzero a
> > pointer of that size, assuming that record/type definitions existed at
> > runtime.) Would you want to do this ?
>
>
> I think so. I also think I would like to be able to specify a type in a
> variable and be able to make-record of that type at runtime. I'm
> attempting to do this in order to allocate a foreign memory block
> inside an around method of initialize-instance. Perhaps there is a
> better way to do this. Was the "would you want to do this" a rhetorical
> question and am I missing the obvious answer here?
>
> Thanks,
>
> Cyrus
>
You could do something like (this steals code from MAKE-RECORD verbatim):
(defun allocate-record (record-or-type-name)
(let* ((ftype (ccl::%foreign-type-or-record record-or-type-name))
(bits (ccl::enxure-foreign-type-bits ftype))
(bytes (if bits
(ceiling bits 8)
(error "Unknown size for foreign type ~S."
(ccl::unparse-foreign-type ftype))))
(p (#_malloc bytes)))
(if (%null-ptr-p p)
(error "Couldn't malloc ~d bytes." bytes))
(#_bzero p bytes)
p))
CCL::%FOREIGN-TYPE-OR-RECORD will map a foreign type specifier or
record name to a data structure that represents that type or record
(perhaps looking in the interface database, i.e., the .cdb files).
Consider a scenario where this is called in a standalone application.
Should the author of that application be required to distribute the
interface database with the application ? (That's not illegal or
immoral or anything, and to some extent it's also a rhetorical
question.)
Note that all that we're doing at this point is determining the
size of the foreign type/record so that we can call #_malloc and
#_bzero with the right args. I realize that there might be other
reasons for wanting information about a type/record in the system
you're working on, but this can be handled via some macrology:
(defmethod initialize-instance ((obj encapsulating-object)
&key record-size-in-bytes
&allow-other-keys)
(with-slots (foreign-pointer) obj
(setq foreign-pointer (#_malloc record-size-in-bytes))))
It'd be awkward to have to say
(make-instance 'encapsulating-object :record-size-in-bytes 17)
but might be less awkward if the user used a macro and rarely called
MAKE-INSTANCE directly:
(defmacro make-encapsulating-object (foreign-type)
;;; Do type -> record-size-in-bytes as in MAKE-RECORD/ALLOCATE-RECORD
(let* ((...)
(size-in-bytes (ceiling bits 8)))
`(make-instance 'encapsulating-object :record-size-in-bytes ,size-in-bytes)))
More information about the Openmcl-devel
mailing list