www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - D/Objective-C Bridge

reply Michel Fortin <michel.fortin michelf.com> writes:
I've been working on creating a usable bridge between D and Objective-C 
for some time and decided today it was working well enough for a first 
release. The bridge is written entirely in D and attempts to provides a 
mostly transparent environment in which Objective-C objects and classes 
are accessible as regular D objects. You can freely send D objects to 
Objective-C method calls and vice-versa, all 
conversions/wrapping/encapsulation being done automatically for you 
with some template-magic.

The goal is mostly to make it workable for writing Mac OS X 
applications using Cocoa. The bridge allows D objects to be 
instantiated from nib files, with outlets and actions being connected 
as any Cocoa programmer would expect.

There are still a few round corners, missing thread-safty, performance 
issues and possibly the lack of Intel support (I don't have an Intel 
Mac to test). There is also much to be written: the bridge requires 
writing a wrapper class for each class in the Cocoa framework we want 
to make available. It's pretty easy thanks to all the templates, but 
it's still time-consuming.

If you're interested, here is the project page (with a download link):

http://michelf.com/projects/d-objc-bridge/

I've also written an introduction article on my blog attempting to 
explain how everything works without writing a book (it could be better 
written):

http://michelf.com/2007/d-objc-bridge/

Things are not documented much right now, but I look forward to improve 
that. The best documentation you can find currently about the internals 
are the many comments in the code, although it's easy to get lost in 
all these templates. The example application is pretty straightforward 
though, and I'm pretty sure the bridge can be used easily without 
having to understand much of how Objective-C works.

-- 
Michel Fortin
michel.fortin michelf.com
http://michelf.com/
Sep 17 2007
next sibling parent reply BCS <ao pathlink.com> writes:
Reply to Michel,

 
 http://michelf.com/2007/d-objc-bridge/
 

404 error
Sep 17 2007
next sibling parent Carlos Santander <csantander619 gmail.com> writes:
BCS escribió:
 Reply to Michel,
 
 http://michelf.com/2007/d-objc-bridge/

404 error

It's http://michelf.com/weblog/2007/d-objc-bridge/ The link in the homepage is also wrong. -- Carlos Santander Bernal
Sep 17 2007
prev sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2007-09-17 23:01:28 -0400, BCS <ao pathlink.com> said:

 Reply to Michel,
 
 http://michelf.com/2007/d-objc-bridge/

404 error

Oops... http://michelf.com/weblog/2007/d-objc-bridge/ -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 17 2007
prev sibling next sibling parent kris <foo bar.com> writes:
This sounds awesome!

Michel Fortin wrote:
 I've been working on creating a usable bridge between D and Objective-C 
 for some time and decided today it was working well enough for a first 
 release. The bridge is written entirely in D and attempts to provides a 
 mostly transparent environment in which Objective-C objects and classes 
 are accessible as regular D objects. You can freely send D objects to 
 Objective-C method calls and vice-versa, all 
 conversions/wrapping/encapsulation being done automatically for you with 
 some template-magic.
 
 The goal is mostly to make it workable for writing Mac OS X applications 
 using Cocoa. The bridge allows D objects to be instantiated from nib 
 files, with outlets and actions being connected as any Cocoa programmer 
 would expect.
 
 There are still a few round corners, missing thread-safty, performance 
 issues and possibly the lack of Intel support (I don't have an Intel Mac 
 to test). There is also much to be written: the bridge requires writing 
 a wrapper class for each class in the Cocoa framework we want to make 
 available. It's pretty easy thanks to all the templates, but it's still 
 time-consuming.
 
 If you're interested, here is the project page (with a download link):
 
 http://michelf.com/projects/d-objc-bridge/
 
 I've also written an introduction article on my blog attempting to 
 explain how everything works without writing a book (it could be better 
 written):
 
 http://michelf.com/2007/d-objc-bridge/
 
 Things are not documented much right now, but I look forward to improve 
 that. The best documentation you can find currently about the internals 
 are the many comments in the code, although it's easy to get lost in all 
 these templates. The example application is pretty straightforward 
 though, and I'm pretty sure the bridge can be used easily without having 
 to understand much of how Objective-C works.
 

Sep 17 2007
prev sibling next sibling parent Mark Wrenn <mark-nospam binarytheory.com> writes:
This is so cool.  I was just wondering about using D for ObjC.

Michel Fortin wrote:
 I've been working on creating a usable bridge between D and Objective-C 
 for some time and decided today it was working well enough for a first 
 release.

Sep 17 2007
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Too good to not post it to Reddit!

http://programming.reddit.com/new
Sep 17 2007
prev sibling next sibling parent reply BLS <nanali nospam-wanadoo.fr> writes:
Michel Fortin schrieb:
 I've been working on creating a usable bridge between D and Objective-C 
 for some time and decided today it was working well enough for a first 
 release. The bridge is written entirely in D and attempts to provides a 
 mostly transparent environment in which Objective-C objects and classes 
 are accessible as regular D objects. You can freely send D objects to 
 Objective-C method calls and vice-versa, all 
 conversions/wrapping/encapsulation being done automatically for you with 
 some template-magic.
 
 The goal is mostly to make it workable for writing Mac OS X applications 
 using Cocoa. The bridge allows D objects to be instantiated from nib 
 files, with outlets and actions being connected as any Cocoa programmer 
 would expect.
 
 There are still a few round corners, missing thread-safty, performance 
 issues and possibly the lack of Intel support (I don't have an Intel Mac 
 to test). There is also much to be written: the bridge requires writing 
 a wrapper class for each class in the Cocoa framework we want to make 
 available. It's pretty easy thanks to all the templates, but it's still 
 time-consuming.
 
 If you're interested, here is the project page (with a download link):
 
 http://michelf.com/projects/d-objc-bridge/
 
 I've also written an introduction article on my blog attempting to 
 explain how everything works without writing a book (it could be better 
 written):
 
 http://michelf.com/2007/d-objc-bridge/
 
 Things are not documented much right now, but I look forward to improve 
 that. The best documentation you can find currently about the internals 
 are the many comments in the code, although it's easy to get lost in all 
 these templates. The example application is pretty straightforward 
 though, and I'm pretty sure the bridge can be used easily without having 
 to understand much of how Objective-C works.
 

Un bon travail! In your Blog you wrote : /D is a statically-typed language, in the same spirit as C++. This means that very little information is known at runtime about D objects: their name, their members, their methods, almost all of this disappear once the program has been compiled. This also mean that you can’t dynamically add classes or methods like you can do in Objective-C ..../ I am not that sure. I guess it is possible to implement runtime reflection based upon compiletime reflection using D 2.x __traits. Kirk (PyD) is most probabely the one who can tell you more. There is also a project called flectioned on DSource http://www.dsource.org/projects/flectioned Bjoern
Sep 17 2007
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2007-09-18 02:51:28 -0400, BLS <nanali nospam-wanadoo.fr> said:

 In your Blog you wrote :
 /D is a statically-typed language, in the same spirit as C++. This 
 means that very little information is known at runtime about D objects: 
 their name, their members, their methods, almost all of this disappear 
 once the program has been compiled. This also mean that you can’t 
 dynamically add classes or methods like you can do in Objective-C ..../
 
 I am not that sure. I guess it is possible to implement runtime 
 reflection based upon  compiletime reflection using D 2.x __traits.

Well, the bridge is written using D 1.x (obviously, since it works on GDC). But I was speaking of *runtime* refletion, which is limited even in 2.x. And the more I think about it, the more I think reflection won't help much anyway in this case. Reflection would be useful to this bridge if you could create new classes at runtime and other code could call the methods of those runtime-created classes... D isn't dynamic enough for that: you can't call a method you don't know yet on a class you don't know about. So even if with runtime reflection you could inspect a D class and encapsulate it into an Objective-C object all at runtime, you couldn't do the reverse: create a D class when you receive an Objective-C object. I'd add that I kind of like the way things are done right now, manually binding the methods you want. For one thing, it makes it possible to use different method names in D and in Objective-C, keeping things clean. For another, it minimize the generated code size. Some D features (like overloading) would be very hard to map directly to Objective-C too (unless you use mangled method names). The syntax to bind methods could use some improvements, although I doubt it can be improved much without adding new features to the D language. Something like this, where you could directly associate the template with the method would be cool, even if I have no idea how it'd work: ObjcBindMethod!("setObject:forKey:") void opIndexAssign(Object obj, Object key) { } Currently it has to be done this way: void opIndexAssign(Object obj, Object key) { } ObjcBindMethod!(opIndexAssign, Object, "setObject:forKey:", Object); repeating the return type and the argument types so the template can find the right method (otherwise you'd get unpredictable results with overloading). Note that *compile-time* reflection is used here to make that work, in a rather hacky way. The way it worked orignally, each of these ObjcBindMethod template instanciation were using a static constructor to add the method to the statically constructed Objective-C class. This posed a problem with the ways static constructors work in D, preventing circular references of modules. I had to find a fix for that. So now, each of these template instanciation adds an empty struct member to the class. That said, "empty" isn't compltly right: the struct has one const static member with the method info for the Objective-C runtime. Then, when building the Objective-C object, I iterate over the tuple of the class (which gives non-static members), find out any struct with a static methodInfo member, and add that method to the Objective-C class. In other word, I use reflection in the bridge, but only as a way to improve the syntax for templates (so you don't have to declare all the bindings at one central place; you can scatter them in your class definition as you like).
 There is also a project called flectioned on DSource
 http://www.dsource.org/projects/flectioned

Hum, so flectioned looks at the symbols in the executable and use that for reflection at runtime... looks nice. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 18 2007
prev sibling parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Michel Fortin wrote:

 I've been working on creating a usable bridge between D and Objective-C 
 for some time and decided today it was working well enough for a first 
 release. The bridge is written entirely in D and attempts to provides a 
 mostly transparent environment in which Objective-C objects and classes 
 are accessible as regular D objects. You can freely send D objects to 
 Objective-C method calls and vice-versa, all 
 conversions/wrapping/encapsulation being done automatically for you with 
 some template-magic.

Is this based anything on the earlier similar work called "Docoa" ? http://dsource.org/projects/docoa
 The goal is mostly to make it workable for writing Mac OS X applications 
 using Cocoa. The bridge allows D objects to be instantiated from nib 
 files, with outlets and actions being connected as any Cocoa programmer 
 would expect.

The program seems to be using "objc_msgSendSuper_fpret", which I'm not sure if it even exists ? At least that's what I googled up on: http://lists.apple.com/archives/Objc-language/2006/Jun/msg00012.html alias objc_msgSendSuper objc_msgSendSuper_fpret; // workaround ?
 There are still a few round corners, missing thread-safty, performance 
 issues and possibly the lack of Intel support (I don't have an Intel Mac 
 to test).

The project compiled (after the above), but the adder doesn't... add. So it seems to be missing some interaction with the action binding ? It does send the event though, so it might just be "a cocoa thing". (i.e. printing out the value to the console in the controller works) On Intel, this was.
 There is also much to be written: the bridge requires writing 
 a wrapper class for each class in the Cocoa framework we want to make 
 available. It's pretty easy thanks to all the templates, but it's still 
 time-consuming.

How do you intend to get around the copyright / distribution problem ? The way it was originally planned for Carbon was with auto-conversion. So that you'd download a program you could run on "your own" headers... Possibly something like SWIG, with auto-generation plus some patches. Nice work! --anders
Sep 18 2007
next sibling parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
 The project compiled (after the above), but the adder doesn't... add.
 So it seems to be missing some interaction with the action binding ?
 It does send the event though, so it might just be "a cocoa thing".
 (i.e. printing out the value to the console in the controller works)

"floatValue" didn't work, for some reason. But intValue/doubleValue did. --anders
Sep 18 2007
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2007-09-18 03:19:22 -0400, Anders F Björklund <afb algonet.se> said:

 Is this based anything on the earlier similar work called "Docoa" ?
 
 http://dsource.org/projects/docoa

I took a look at Docoa a little while ago, but no, nothing is based on it. I've written it all from scratch. I think the only thing we have in common (and which could be harmonized) are the Objective-C runtime declarations for types and functions (converted from C headers).
 The goal is mostly to make it workable for writing Mac OS X 
 applications using Cocoa. The bridge allows D objects to be 
 instantiated from nib files, with outlets and actions being connected 
 as any Cocoa programmer would expect.

The program seems to be using "objc_msgSendSuper_fpret", which I'm not sure if it even exists ? At least that's what I googled up on: http://lists.apple.com/archives/Objc-language/2006/Jun/msg00012.html alias objc_msgSendSuper objc_msgSendSuper_fpret; // workaround ?

Ah, I see you're on Intel. :-) Basically, because of the architecture, the runtime on Intel use a different function to send messages with floating-point return values. objc_msgSendSuper_fpret seems to be missing in Apple's headers for the runtime (so I didn't put it in), but without it you don't have any mean to call a method with a floating point return value. I'd suggest you try adding this instead: version (X86) double objc_msgSendSuper_fpret(objc_super* superContext, SEL theSelector, ...) after function definintion objc_msgSendSuper_stret in objc/runtime.d. This is the logical choice for the name of the function, but if this doesn't work, I'd suggest tracing with the debugger into a real Objective-C program to check. That's something I can't do on my machine.
 There are still a few round corners, missing thread-safty, performance 
 issues and possibly the lack of Intel support (I don't have an Intel 
 Mac to test).

The project compiled (after the above), but the adder doesn't... add. So it seems to be missing some interaction with the action binding ? It does send the event though, so it might just be "a cocoa thing". (i.e. printing out the value to the console in the controller works)

It's missing its floating point return value. :-)
 There is also much to be written: the bridge requires writing a wrapper 
 class for each class in the Cocoa framework we want to make available. 
 It's pretty easy thanks to all the templates, but it's still 
 time-consuming.

How do you intend to get around the copyright / distribution problem ?

Not sure yet. Perhaps it should be based on GNUStep instead of Cocoa (while still making sure it works with Cocoa). Or perhaps we should just ask Apple, they seem pretty cool with language bridges these days (they're bundling PyObjC and RubyCocoa with Leopard I've heard).
 The way it was originally planned for Carbon was with auto-conversion.
 So that you'd download a program you could run on "your own" headers...
 Possibly something like SWIG, with auto-generation plus some patches.

I'm not sure about autoconversion. What's interesting when writing manually the wrappers is that you can shorten the method names. Things wouldn't be too bad for methods like this one: [dict setObject:object forKey:key]; <=> dict.setObjectForKey(object, key); although I think binding it to opIndexAssign (like I did) makes more sense. But look at what it would do for NSAlert: [NSAlert alertWithMessageText:msg defaultButton:default alternateButton:alt otherButton:other informativeTextWithFormat:info]; <=> NSAlert.alertWithMessageTextDefaultButtonAlternateButtonOtherButtonInformativ TextWithFormat(msg, default, alt, other, info); Erk. Sure, things could be patched, but I have the feeling a lot of patches are going to be needed. I wonder how Apple did their bridge with Java... oh, I see: that method just isn't there. Which makes me think that, performance-wise, it may be a good idea to leave a few methods unbridged too. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 18 2007
next sibling parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Michel Fortin wrote:

 I took a look at Docoa a little while ago, but no, nothing is based on 
 it. I've written it all from scratch. I think the only thing we have in 
 common (and which could be harmonized) are the Objective-C runtime 
 declarations for types and functions (converted from C headers).

As far as I know, the Docoa project is dead. If not, it's now obsolete.
 This is the logical choice for the name of the function, but if this 
 doesn't work, I'd suggest tracing with the debugger into a real 
 Objective-C program to check. That's something I can't do on my machine.

We can take it off this forum. I subscribed to your newsletter,er,list.
 It does send the event though, so it might just be "a cocoa thing".
 (i.e. printing out the value to the console in the controller works)

It's missing its floating point return value. :-)

Not sure about that, since the return type is "void" for setFloatValue:
 How do you intend to get around the copyright / distribution problem ?

Not sure yet. Perhaps it should be based on GNUStep instead of Cocoa (while still making sure it works with Cocoa). Or perhaps we should just ask Apple, they seem pretty cool with language bridges these days (they're bundling PyObjC and RubyCocoa with Leopard I've heard).

I think it would be cool if GNUstep was supported, regardless of Apple.
 Erk. Sure, things could be patched, but I have the feeling a lot of 
 patches are going to be needed. I wonder how Apple did their bridge with 
 Java... oh, I see: that method just isn't there.

The JavaBridge is deprecated, so I don't think it sees much new stuff. --anders
Sep 18 2007
prev sibling parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Michel Fortin wrote:

 The way it was originally planned for Carbon was with auto-conversion.
 So that you'd download a program you could run on "your own" headers...
 Possibly something like SWIG, with auto-generation plus some patches.

I'm not sure about autoconversion. What's interesting when writing manually the wrappers is that you can shorten the method names. Things wouldn't be too bad for methods like this one: [dict setObject:object forKey:key]; <=> dict.setObjectForKey(object, key); although I think binding it to opIndexAssign (like I did) makes more sense.

Surely opIndexAssign can just call the traditional function name, no ? (i.e. have opIndex and opIndexAssign call objectForKey/setObjectForKey) The Carbon conversion was scrapped in favor of wxWidgets, by the way. Much easier to #include <Carbon/Carbon.h>, and is also cross-platform. So another dead project: http://dsource.org/forums/viewforum.php?f=68 --anders
Sep 18 2007