[Prev][Next][Index][Thread]

Re: Objective C bridge (Long)



On Saturday, March 10, 2001, at 12:30 PM, Dustin Voss wrote:

> I have read Apple's documentation of the Java bridge, but it is way too  
> skimpy on details to use as a model. 

Yes. The public headers for the bridge are quite useful, though.

> That means we need to keep a reference around on the Dylan side of  
> things, to keep the Dylan stub from getting garbage-collected. When the  
> framework finally releases the Obj C stub, we can remove the Dylan  
> reference. 

How will Dylan's GC interact with Objective-C's reference counting? If the Dylan GC will scan the Objective-C data structures, it will know when the Dylan objects are no longer referenced. If not, pop the objects in a hashtable with a callback method that gets called to remove them when the Objective-C class is deallocated.

> ...So basically, that's the plan. I don't think there are actually that  
> many factors to consider here. 

That sounds good. Looking at Apple's public Objective-C headers, it should be possible to create Objective-C classes and add methods at runtime, I just don't know how to initialize an objc_class struct. I'm working on it. :-)

PyObjC at http://www.sourceforge.com/ is interesting. It's a Python library to call Objective-C code. Method calls are handled as NSInvocation objects, and id/SEL/Class objects are wrapped for Python.

> I'd like the syntax to look something like this, but I'm not sure  
> obj-c-bridge-definer will be evaluated at run-time or compile-time. 

Macros can evaluate to method calls. This can be very useful for building paramter lists or adding glue code. Objective-C methods take this and sel as hidden parameters.

> // Sub-class of NSView with Dylan-specific instance variables. 
> define class <my-subview> (<obj-c-bridge>) 
>   slot my-slot; 
> end class; 

The Java bridge has a parallel java class hierarchy for the obj-c classes. To use Dylan classes in obj-c frameworks, Dylan will either need the same or the classes will have to pose-as the class they're meant to be a subclass of. 

> // An overridden NSView method. 
> define method draw-rect (view :: <my-subview>, rect :: <rect>) 
>   view.frame := rect;          // "frame" is inherited Obj-C variable 
>   view.super-set-background ($red); 
> end method; 

View will be the hidden this parameter, and between that and rect there's a hidden sel parameter. The Java bridge automatically converts Strings and other much-used types. The Dylan bridge should definitely do this, although an <NSString> subclass of <string> should work well.

> // Link the <my-subview> class to the Objective C runtime. This macro 
> // will add methods and slots to the Dylan class. I think the class 
> // should contain <function> slots to mimic the method/variable combo 
> // of Obj C classes and allow delegates. 
>  
> define obj-c-bridge <my-subview> ("NSView") 
>   // Declare Obj C super-class functions to use, but not override. 
>   inherit "- setBackground:(NSColor)" as super-set-background; 
>   // Exported Dylan functions     
>   export draw-rect as "- drawRect:(NSRect)"; 
> end; 

Cool. Macrology could build the selector and coerce any parameters that need coercing. Macros can also whack names to strings, which can be useful. This could be combined with the class definition, certainly for the user if not for the macros.

> In an earlier thread by Rob and, um...Dennis De Mars, they mentioned a  
> problem with the Obj C function names and Dylan functions with keyword  
> parameters. Basically, all methods on a generic function must use the  
> keyword params declared in the generic, but Obj C doesn't require any  
> consistency in keyword parameters. Rather than struggle with this, I can  
> simply allow different method names on the Obj C and Dylan sides,  
> specified by the programmer. 

It's probably best to enforce Objective-C naming rules on Dylan, as Dylan has a richer set of characters available to names. For parameter lists, Dylan conventions are better as the lists have to be consistent.

> Rob wrote: 
>  
> > > *  I want to be able to create an Obj C stub that fits in the Obj C   
> > > class hierarchy, so I can subclass NSWindowController (for example).  
> >  
> > It's more of a facade, I think. See how Apple make proxies for Java  
> > Objects. I came up with an incredibly overblown solution using NSProxy,  
> > but a simple facade is much better, I think. :-) I can't figure out how  
> > Objective-C classes are added to the dispatch table in the Objective-C  
> > runtime. I think it's runtime-specific. :-( 
>  
> It may well be. The runtime offers classes for dispatching messages,  
> adding classes, finding classes by name, retrieving variables and  
> methods of a class by name, and editing a class's method list. Looks  
> easy for the OS X runtime. 

Yes. 

>  
> > > *  Methods of the Obj C stubs should map to Dylan methods.  
> >  
> > If each Obj-C method calls a Dylan callback, no problem. It would be  
> > harder, but still possible, to crack the Objective-C method name mangling  
> > scheme and add Dylan callbacks to the hashtable Objective-C uses to look  
> > up methods. 
>  
> I think that's overkill. I bet objc_msgSend will do the job nicely, once  
> the stub class is installed into the run-time. 

That allows the method to be called. It must be registered before it can be called, and Objective-C methods must be registered on a class. There are methods to do this in objc-runtime.h and objc-class.h, but the signature of the Dylan callback has to be right, objects must be coerced, and we need to generate a  signature string (like for Java) for the method.

>  
> > > *  Obj C exceptions should map to Dylan exceptions. This'll be easy.  
> >  
> > How will you do this? I'm interested. 
>  
> This is really easy. I assume the user won't be writing Objective C  
> code, so any Obj C exceptions will be thrown by the framework and  
> percolate all the way to the top. I can change the last-resort exception  
> handler function. I'll just redirect that to an exported and  
> C-compatible Dylan function, which can translate the NSException to some  
> <obj-c-exception> object and signal it. Then the normal Dylan  
> exception-handling system takes over. 

That's a very elegant solution.

- Rob.

--
Rob Myers - http://www.robmyers.org/dylan
"The idea behind Dylan-to offer a range of dynamism appropriate to each piece of an application-feels right, and after using Dylan you will become frustrated with C++ and Java." - Software Development Magazine.