[Openmcl-devel] Retain/Release and the ObjC Bridge

Gary Byers gb at clozure.com
Thu Aug 30 03:52:18 PDT 2007

--On August 28, 2007 8:59:33 PM -0700 Brent Fulgham <bfulg at pacbell.net> 

> Gary,
> The new Cocoa bridge is great to work with, but I'm a little confused as
> to the semantics of releasing data from the bridge.  Should we treat the
> Lisp objects returned by API calls just as we would in C (i.e., we must
> manually call release in many cases), or does OpenMCL ever clean up when
> objects go out of scope?
> Example:
>  (let* ((Name         (%make-nsstring (native-translated-namestring
> File)))
>         (url          (#_CFURLCreateWithFileSystemPath (%null-ptr) Name
> #$kCFURLPOSIXPathStyle #$NO))
>         (imageSrcRef  (#_CGImageSourceCreateWithURL url (%null-ptr)))
>         (imageRef     (#_CGImageSourceCreateImageAtIndex imageSrcRef 0
> (%null-ptr)))
>         (uprightImage (#/imageWithCGImage: (@class c-i-image) imageRef)))
>    (if (%null-ptr-p uprightImage)
>        (error "cannot decode texture file \"~A\""
> (native-translated-namestring Filename)))
>      (let* ( ;; Flip image (if necessary)
>             (image (if Flip-Vertical (#/imageByApplyingTransform:
> uprightImage transform) uprightImage))
>             (rect (#/extent image))
>             (depth (#_CGImageGetBitsPerPixel imageRef))
>             (width (#_CGImageGetWidth imageRef))
>             (height (#_CGImageGetHeight imageRef))
>             (bytesPerRow (#_CGImageGetBytesPerRow imageRef))
>             (bytesPerPixel (truncate depth 8))
>             (bitmap (#/initWithCIImage: (#/alloc (@class
> n-s-bitmap-image-rep)) image))
>             (Codec (#/bitmapFormat bitmap))
>             (samples-per-pixel (#/samplesPerPixel bitmap)))
>         (when Verbose
>           (format t "~%-loading image ~A size: ~A x ~A, depth: ~A"
> Filename width height depth)
>           (format t "---> bytes-per-pixel/samples-per-pixel: ~A/~A~%"
> bytesPerPixel bytesPerPixel) ;samples-per-pixel)
>           (format t "---> bitmap format: ~A~%" (#/bitmapFormat bitmap)))
>         ;; FIXME:  Need Core Image filters to change depth if required
>         (when Forced-Depth (setq depth Forced-Depth)) ; Currently we
> don't do anything with this ...
>         (#_CFRelease image)
>         (#_CFRelease imageRef)
>         (#_CFRelease imageSrcRef))))))
> This code seems to work fine for me, but I'm wondering if the CFRelease
> calls I am making are always necessary.  Or am I perhaps missing some
> (perhaps the URL should be released, too?)

The lisp doesn't automatically release any CoreFoundation or ObjC objects.
(And yes, AFAIK the CFURL needs to be released, too.)

> And to add further confusion, will the answer to the above change when
> Objective C 2.0 is used? -- I would imagine it must if garbage collection
> is used.

I'm not sure what's been publicly said about ObjC 2.0 GC, so let's talk
hypothetically ...

There are probably some systems in the world that try to mix manual
(#/retain / #/release or #_malloc / #_free) memory management with
automatic (GC-based) memory management, but such systems likely make
the GC's job harder (since the GC would have to worry about pointers
to deleted or reallocated objects at virtually every step.)

If code has to be compiled for (and/or run in) both GCed and non-GCed
environments, one way of ensuring that the right thing happens in both
cases is to ensure that #/retain and (especially) #/release and #/dealloc
don't do anything when the GC is in use.

In the reference-counting runtime, it's a common idiom for a #/dealloc
method to deallocate other (non-object) resources (like file descriptors
and memory buffers.)  Since #/dealloc would never be called automatically
if the GC is in use, it's necessary for a GC-based runtime to provide
another mechanism whereby this kind of finalization/cleanup can be
performed when necessary.

> Thanks,
> -Brent

More information about the Openmcl-devel mailing list