[Openmcl-devel] Allocate heap and call C question

Andrew P. Lentvorski, Jr. bsder at mail.allcaps.org
Mon Jul 5 23:47:34 UTC 2004


On Jul 5, 2004, at 4:43 AM, Gary Byers wrote:

> Since there's no reliable way to pass a lisp object to foreign code,
> you generally have to do something like what you're trying to do by
> allocating a foreign array, copying the lisp array's contents to that
> foreign array, passing the foreign array to foreign code, and possibly
> copying the foreign array's elements back to the lisp array.  (The
> first few of these steps is basically what things like WITH-CSTRS do.)

So, if I understand what you are saying, there is no way to mark a 
specific Lisp object such that the garbage collector will not screw it 
up.  Personally, I think that is a significant hole, but now that I 
know that is the case, I can work around it.

So, I would like to allocate a foreign array on the heap such that the 
Lisp GC won't touch it and get back a macptr.  The only way that I know 
of to do this is to call malloc as an external-call like so:

? (setq am (external-call "_malloc" :unsigned-int 16 :address))
#<A Mac Pointer #x101C60>

Is there a better/different/more Lisp-y way of doing this?  If not, 
fine.  However, I would hate to reinvent the wheel if something already 
exists.

> Note that the GC would be disabled for all threads if any thread was
> inside a WITH-POINTERS-TO-LISP-OBJECTS, and this can be undesirable.
> (Whether it is undesirable or not depends on the application, and
> the developer of that application should have enough rope to hang
> themselves ...)

Is there a particular reason why individual objects cannot be 
allocated/marked such that the GC does not tinker with them?  This 
question probably demonstrates my massive ignorance of Lisp 
implementation.

To a certain extent, I'm not overly concerned with speed as long as 
there exists *some* mechanism for getting back and forth to C even if 
it is slow.  Simply using an external API *at all* is currently 
problematic in most Lisps without writing lots of wrappers, recompiling 
C code, recompiling the Lisp code, etc.  My goal is just to get to a 
level that allows the use of something along the lines of the Python 
ctypes module.  Sure, you can shoot yourself in both feet, chop off 
your hands, and hang yourself simultaneously; however, you can also get 
lots of work done before committing to the effort required to do an 
official wrapper of an API.

> FWIW, in the code in your message you were calling %GET-UNSIGNED-LONG
> (and SETF thereof) on successive byte indices; you'd typically want
> to copy 32-byte words that are 4 bytes apart:

Ah.  That probably needs to be made more explicit in the documentation. 
  It certainly makes the offset field of dubious utility.  C programmers 
expect that adding an offset to a pointer-to-X automatically handles 
the appropriate arithmetic (ie. if int *p; p = 0x54679800; then p+1 == 
0x54679804)

So, what I have now is:

Welcome to OpenMCL Version (Beta: Darwin) 0.14.2-040506!
? ;; Set the memory elements from an array
(defun set-mem (m a)
   (dotimes (i (length a))
       (setf (%get-signed-long m (* i 4)) (aref a i))))
SET-MEM
? ;; Dump the memory elements out afterward
(defun print-mem (m l)
   (dotimes (i l)
       (format t "~A~%" (%get-signed-long m (* i 4)))))
PRINT-MEM
? (setq am (external-call "_malloc" :unsigned-int 16 :address))
#<A Mac Pointer #x101C60>
? (open-shared-library 
"/Users/andrewl/openmcl/openmcl/gtk/libptrtest.dylib")
#<SHLIB /Users/andrewl/openmcl/openmcl/gtk/libptrtest.dylib #x6384A36>
? (setq a #(78 92 10 4))
#(78 92 10 4)
? (set-mem am a)
NIL
? (print-mem am 4)
78
92
10
4
NIL
? (external-call "_ip_ip_test" :address am :address)
Entered ip_ip_test:
Data In: 0x101c60
C:I:0 *(p+i):78
C:I:1 *(p+i):92
C:I:2 *(p+i):10
C:I:3 *(p+i):4
Reversing memory chunk
C:I:0 *(p+i):4
C:I:1 *(p+i):10
C:I:2 *(p+i):92
C:I:3 *(p+i):78
Exited  ip_ip_test:
#<A Mac Pointer #x101C60>
? (print-mem am 4)
4
10
92
78
NIL

This seems to work.  Do I have any hidden mistakes buried in this code 
that are going to catch up with me later?  Or is there a better way of 
doing this?

Thanks for all the help,
-a








More information about the Openmcl-devel mailing list