[Openmcl-devel] Setting a toplevel function for build-application

Ron Garret ron at flownet.com
Tue Sep 17 17:38:23 UTC 2013

On Sep 16, 2013, at 2:27 AM, Pascal J. Bourguignon wrote:

> Ron Garret <ron at flownet.com> writes:
>> I can't figure out how to set a toplevel function for build-application.  The docs say:
>> "The best source of information about writing your own toplevel is the
>> Clozure CL source code, especially the implementations of
>> TOPLEVEL-FUNCTION in "ccl/level-1/l1-application.lisp"
>> In that file there is no example of calling build-application, but there is a (generic) function called toplevel-function.
>> If I do this:
>> (build-application :name "testapp" :directory #P"~/Desktop/" :copy-ide-resources t)
>> the resulting application (mostly) works fine [1], but if I do this:
>> (build-application :name "testapp" :directory #P"~/Desktop/" :copy-ide-resources t
>>                   :toplevel-function 'toplevel-function)
>> The resulting application crashes with hundreds of console message like this:
>> 9/14/13 12:45:08 PM	[0x0-0x3ae9ae6].com.clozure.store.ccl-x8664[90745]	> While executing: #<CCL::STANDARD-KERNEL-METHOD NO-APPLICABLE-METHOD (T)>, in process toplevel(8).
>> 9/14/13 12:45:08 PM	[0x0-0x3ae9ae6].com.clozure.store.ccl-x8664[90745]	> Error: There is no applicable method for the generic function:
>> 9/14/13 12:45:08 PM	[0x0-0x3ae9ae6].com.clozure.store.ccl-x8664[90745]	>          #<STANDARD-GENERIC-FUNCTION CCL::UI-OBJECT-DO-OPERATION #x3020000BC73F>
>> 9/14/13 12:45:08 PM	[0x0-0x3ae9ae6].com.clozure.store.ccl-x8664[90745]	>        when called with arguments:
>> 9/14/13 12:45:08 PM	[0x0-0x3ae9ae6].com.clozure.store.ccl-x8664[90745]	>          (#<A Dead Mac Pointer> :BREAK-OPTIONS-STRING T)
>> Clues appreciated.
>> What I'm actually trying to do is build a standalone application that
>> just opens a webkit window and does nothing else (i.e. no listener).
>> But I want to do it programmatically, without a nib file.
>> rg
>> [1] Actually, the resulting application complains about not being able to find the header directory, but that's easy to fix.
> For a GUI application, I use :toplevel-function nil  (but then I guess
> that defaults to the toplevel-function generic function in
> l1-applications).

Yes, and that function is not a function but a generic function with several methods defined on it.  So reverse-engineering what it actually does is not trivial.

> The initialization of a Cocoa application is done thru the NSApplication
> instance anyways.

Yes, I know that.  What I don't know is how the initialization of the NSApplication interacts with the initialization of Lisp in general and the IDE in particular.  But at some point in the process, enough initialization has happened that the IDE is able to open a listener window.  All I want to do (for now) is to intercept the process at (or after) that point and have it open a webkit window instead.  That seems like it should be straightforward, but I have tried countless permutations and have been unable to get the resulting application to do anything other than crash on launch.

> Of course, saving an image kills all the Objective-C objects, so you
> have to use the various hooks (ccl:*lisp-cleanup-functions*
> ccl:*save-exit-functions* ccl:*restore-lisp-functions*
> ccl:def-load-pointers ccl:*lisp-startup-functions*) available to clean
> up and restore those Objective-C objects.

The existence of these functions is news to me.  DEF-LOAD-POINTERS is particularly intriguing.  It doesn't seem to be documented in any way, and I can't figure out what it's supposed to do by looking at the code.

In any case, I am aware that objC objects need to be reconstructed.  Does that mean that frameworks need to be reloaded?

> In
> https://gitorious.org/patchwork/patchwork/source/881de93680c96ddd88cbf5ce43764e6843e6327a:src/mclgui
> I have code to "archive" and "unarchive" Objective-C objects (including
> circular references), but it's very fresh, let's say it's at the proof
> of concept stage, but it can indeed transport eg. menus across saved
> images (some work/debugging is still needed to complete the reviving of
> objects like windows: the objects are unarchived, but they need to be
> re-mapped on screen, and so on).   cf. files wrapper.lisp
> objc-persistent.lisp system.lisp etc.

That looks very cool, but I'm pretty sure this is not the problem I'm having.

> So far, the trick is that lisp code should re-instanciate explicitely
> all the Objective-C objects when the application is relaunched.

I believe I am doing that.  Among the many, many permutations I have tried is:

(setf ccl:*lisp-startup-functions*
 (list (lambda ()
         (load "ccl:examples;webkit")
         (ccl::browser-window "http://openmcl.clozure.com"))))

That, of course, didn't work either.  In this case I get -- no exaggeration -- tens of thousands of stack overflow messages in the OS X console.


More information about the Openmcl-devel mailing list