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

Re: Objective C bridge



On Friday, March 9, 2001, at 07:30 PM, Dustin Voss wrote:

> *  I want to be able to instantiate and call on Obj C objects. 

This is easily done by calling the c functions that Objective-C syntax gets transformed into by the Objective-C preprocessor.

> *  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. :-(

> *  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.

> *  Instance variables of the Obj C stub should map to slots of a Dylan  
> stub. I considered only supporting methods, to avoid any potential  
> garbage collection or reference counting issues with variables, but I  
> believe Interface Builder support will require instance variables.. 

This is interesting. Dylan treats slot access as a method call, Objective-C as a value reference. You'll have to have no public member variables and use accessor functions, which can map to Dylan methods.

> *  Obj C exceptions should map to Dylan exceptions. This'll be easy. 

How will you do this? I'm interested.

> *  I'd like to do all this without relying on any pre-processing. 

This is hard: the best way is a toy preprocessor like Apple use for the Obj-C/Java bridge. Some Dylan macros and some hard work on the part of the programmer could do without a preprocessor (I wrote the Dylan Carbon library by hand. Hundreds of melange-c calls. Ugh....)

> I've got some ideas, but it's late and I'm tired, so I'll post them  
> tomorrow or this weekend. Sorry about the tease! :-) 

Looking forward to it. I can't find the document I wrote on the subject. :-(

Here's a Gwydion d2c-only, Apple Objective-C only (IIRC), calling program. No callbacks or classes.

- Rob.

module: objective-c


// c-include for Apple Objective-C

c-include( "objc/objc.h" );


// Objective-C Types

define constant <objective-c-id> = <statically-typed-pointer>;
define constant <objective-c-class> = <statically-typed-pointer>;
define constant <objective-c-selector> = <statically-typed-pointer>;


// Methods


// get-objective-c-selector

define method get-objective-c-selector( selector-name :: <string> )
=> ( result :: false-or( <objective-c-selector> ) )
    let selector-name-c-string = as( <c-string>, selector-name  );
    let result = call-out( "sel_getUid", ptr:, ptr: selector-name-c-string.raw-value );
    if( result = 0 )
        #f;
    else
        as( <objective-c-selector>, result );
    end if;
end method get-objective-c-selector;


// get-objective-c-class

define method get-objective-c-class( class-name :: <string> )
=> ( result :: false-or( <objective-c-class> ) )
    let class-name-c-string = as( <c-string>, class-name  );
    let result = call-out( "objc_getClass", ptr:, ptr: class-name-c-string.raw-value );
    if( result = 0 )
        #f;
    else
        as( <objective-c-class>, result );
    end if;
end method get-objective-c-class;


// obj_msg_send

define method send-objective-c-message( class :: <objective-c-class>, message :: <objective-c-selector> )
=> ( result :: <objective-c-id> )
    let result = call-out( "objc_msgSend", ptr:, ptr: class.raw-value, ptr: message.raw-value );
    as( <objective-c-id>, result );
end method send-objective-c-message;


// main

define function main(name, arguments)
    let alloc = get-objective-c-selector( "alloc" );
    let init = get-objective-c-selector( "init" );
    let object-class = get-objective-c-class( "NSObject" );
    let my-instance = send-objective-c-message( object-class, alloc );
    send-objective-c-message( my-instance, init );

    format-out("Allocated and initialized NSObject instance.\n");
  exit-application(0);
end function main;

// Invoke our main() function.
main(application-name(), application-arguments());



--
Rob Myers - http://www.robmyers.org/dylan
Advanced Free Software Development Tools -
http://www.gwydiondylan.org/