[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)

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

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
  (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

(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