Re: Thinking (again) about an Objective-C bridge
Bruce Mitchener <[email protected]>
| Newsgroups | gmane.comp.lang.dylan.gwydion.devel |
|---|---|
| Message-ID | <CA+esKjMKbiAy5xbWrjYRbxh_yd-RrNPw0rSrW79Ph8UFefi3cg@mail.gmail.com> |
Rob,
I've looked at your bridge before. In Gwydion, you just used call-out to
directly invoke stuff, so there wasn't a Dylan level syntax for doing an
arbitrary message send. You had a script (i2d) that read through the
Objective C headers and generated bindings, with each one generating the
required call-outs.
The equivalent approach in Open Dylan using %call-c-function would be
something like:
let c = objc/get-class("NSObject");
let s = objc/register-selector("alloc");
let o
= primitive-wrap-machine-word
(%call-c-function("objc_msgSend")
(id :: <raw-machine-word>, sel :: <raw-machine-word>)
=> (obj :: <raw-machine-word>)
(primitive-unwrap-machine-word(c.raw-class),
primitive-unwrap-machine-word(s.raw-selector))
end);
That's great and that works. However, once you go and add another
invocation with a different signature, like this:
let s2 = objc/register-selector("alloc2");
let o2
= primitive-wrap-machine-word
(%call-c-function("objc_msgSend")
(id :: <raw-machine-word>, sel :: <raw-machine-word>, val ::
<raw-integer>)
=> (obj :: <raw-machine-word>)
(primitive-unwrap-machine-word(c.raw-class),
primitive-unwrap-machine-word(s2.raw-selector),
integer-to-raw(3))
end);
You'll end up with compile failures like this:
/Users/bruce/Development/dylan/objc-dylan/_build/build/objc-test-suite-app/../objc-test-suite/objc-test-suite.c:200:14:
error: conflicting types for 'objc_msgSend'
extern DWORD objc_msgSend (DWORD, DWORD, DSINT);
^
/Users/bruce/Development/dylan/objc-dylan/_build/build/objc-test-suite-app/../objc-test-suite/objc-test-suite.c:199:14:
note: previous declaration
is here
extern DWORD objc_msgSend (DWORD, DWORD);
^
/Users/bruce/Development/dylan/objc-dylan/_build/build/objc-test-suite-app/../objc-test-suite/objc-test-suite.c:1086:24:
error: too many arguments to function call, expected 2, have 3
objc_msgSend(T8, T9, T11);
~~~~~~~~~~~~ ^~~
/Users/bruce/Development/dylan/objc-dylan/_build/build/objc-test-suite-app/../objc-test-suite/objc-test-suite.c:199:1:
note: 'o
bjc_msgSend' declared here
extern DWORD objc_msgSend (DWORD, DWORD);
^
This is because the generated C specifies the prototype and 2 different
signatures means you get conflicting prototypes. (We don't support varargs
as far as I can tell.) We could hack things to emit a prototype without
any args taking advantage of the special meaning of void objc_msgSend() in
C, but that's not going to help us deal with different return values.
That's why I see things being somewhat difficult and the best approach
being to extend the compiler to lend a hand.
- Bruce
On Fri, Jun 14, 2013 at 5:48 PM, Rob Myers <[email protected]> wrote:
> On 14/06/13 04:25, Bruce Hoult wrote:
>
>> Ideally, what you want is:
>>
>> - grab the symbols for the method and additional argument names
>> - convert to strings and concatenate
>> - create a global variable with that name (prefixed) to hold the
>> selector value.
>> - add the var and string to a hash table (or generate code) to look up
>> the selector value at program startup
>>
>
> Yes that sounds good.
>
> I wrote an Objective-C bridge for Gwydion, the notes may be useful:
>
> https://github.com/dylan-**hackers/GD_2_4/tree/master/**platform/cocoa<https://github.com/dylan-hackers/GD_2_4/tree/master/platform/cocoa>
>
> - Rob.
>
> ______________________________**_________________
> hackers mailing list
> [email protected]
> https://lists.opendylan.org/**mailman/listinfo/hackers<https://lists.opendylan.org/mailman/listinfo/hackers>
>
_______________________________________________
hackers mailing list
[email protected]
https://lists.opendylan.org/mailman/listinfo/hackers