[erlang-questions] client in erlang server in objective C

87 views
Skip to first unread message

Joe Armstrong

unread,
Jul 14, 2012, 12:27:49 PM7/14/12
to Erlang
I want the following:

- Client in erlang (easy)
- Server in objective C (I'm thinking Mac OS-X lion - xcode 4.2 - cocoa)
- socket communication

[[ I'm a complete beginner with xcode/objective C ]]

Has anybody written a simple objective C client that opens a port
waits for a message then executes a callback. This should be non-blocking
and be integrated with the "standard" dispatcher top-loop.

I'm confused by the profusion of classes that almost do this.

Has anybody implemented this, or have pointers to a good place to start.

Cheers

/Joe
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions

Bob Ippolito

unread,
Jul 14, 2012, 12:56:09 PM7/14/12
to Joe Armstrong, Erlang
The best way to do this now is to use Grand Central Dispatch. Your listening socket and the connected sockets are just a dispatch sources that can call blocks on a queue when stuff happens. I believe there's a wrapper for this on github called AsyncSocket that abstracts things a bit (on my phone so I don't have all of my notes). 

Anthony Molinaro

unread,
Jul 17, 2012, 5:48:24 PM7/17/12
to Joe Armstrong, Erlang
What about thrift http://thrift.apache.org/

It's RPC style so you describe function calls, erlang clients are easy,
the objective-c server would be generated for you (other than the
body of the function).

I've been using thrift to talk java->erlang and erlang->java, so
talking erlang->objective-c should be straightforward.

Some examples http://wiki.apache.org/thrift/ThriftUsageObjectiveC

-Anthony
--
------------------------------------------------------------------------
Anthony Molinaro <anth...@alumni.caltech.edu>

Joe Armstrong

unread,
Jul 18, 2012, 4:10:39 AM7/18/12
to Joe Armstrong, Erlang
That's a very interesting idea. I haven't used thrift - but if the server
side code exists in Objective C this would be very interesting.

(I tried to build thrift but the build failed :-)


I've now actually got an erlang client talking to an objective C
server - using AsnycSocket that Bob suggested but I can only exchange strings.

Now I need to figure out how to do build dynamic method calls in objective C.

In objective C I'd write

[button setTitle:@"click me"]

In Erlang I'd like to encode this as a string
send it to objective C decode it and evaluate it.

I'd like to do something like

send("button", "setTitle", [{string,"click me"}])

In erlang

or to encode [foo this:123 that:@"yea"] as

send("foo", "this:that", [{integer,123},{string,"yea"}])

Then I'd like to serialize this as a string (in Erlang) and decode it
and evaluate it in Objective C

Any ideas how to do this?

/Joe

Dmitry Klionsky

unread,
Jul 18, 2012, 4:42:30 AM7/18/12
to erlang-q...@erlang.org
Hi Joe,

NSSelectorFromString, NSClassFromString and others are your friends here.

For more detail have a look at:

Objective-C Runtime Programming Guide
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Introduction/Introduction.html

Objective-C Programming Language
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html

Also I would also suggest you to evaluate the protobuffs. In my opinion
the protobuffs are more concise and clear.
There a couple of Objective-C implementations available:
http://code.google.com/p/metasyntactic/wiki/ProtocolBuffers
https://github.com/booyah/protobuf-objc


Best regards,
Dmitry Klionsky
--
Best regards,
Dmitry Klionsky

Dmitry Klionsky

unread,
Jul 18, 2012, 6:07:55 AM7/18/12
to erlang-q...@erlang.org
Decided to help you a little further:

The problem is you can't just send("button", ...), because the "button"
is not a symbol, but a NSButton's class (or something like this) instance.
I'm not sure because I've never done any MacOX programming, but iOS.
And in order to send a message to an instance you need to know it. So,
in general, your workflow should be like this:

Erlang side:
%% create button
send
{create_instance, {string, "NSButton"}}
receive
{ok, Instance}

%% set button's title
send
{perform, {integer, Button} {string, "setTitle:"}, {string, "click me"}}
receive
ok


Objective-C side

On receiving {create_instance, {string, Clazz}}:

// note that `Class' is a reserved word
id instance = [[NSClassFromString(Clazz) alloc] init];
if (instance) {
reply {ok, instance};
} else {
reply {error, @"No such class"}
}

On receiving {perform, {integer, Instance}, {string, Selector}, {string,
Object}}:
SEL sel = NSSelectorFromString(Selector);
if (sel) {
if ([Instance respondsToSelector(sel)]) {
[Instance performSelector:sel withObject:Object];
reply ok;
} else {
reply {error, @"No such selector"};
}
} else {
reply {error, @"Invalid selector"}
}

This was a little messy, but hopefully you will get the idea.

Joe Armstrong

unread,
Jul 18, 2012, 8:16:42 AM7/18/12
to Dmitry Klionsky, erlang-q...@erlang.org
On Wed, Jul 18, 2012 at 12:07 PM, Dmitry Klionsky <dm.kl...@gmail.com> wrote:
> Decided to help you a little further:

Thanks - I appreciate this ...
I have a few more questions (inline)

>
> The problem is you can't just send("button", ...), because the "button" is
> not a symbol, but a NSButton's class (or something like this) instance.
> I'm not sure because I've never done any MacOX programming, but iOS.
> And in order to send a message to an instance you need to know it. So, in
> general, your workflow should be like this:
>
> Erlang side:
> %% create button
> send
> {create_instance, {string, "NSButton"}}
> receive
> {ok, Instance}

question 1:
Is Instance an integer here? (see question 3)

>
> %% set button's title
> send
> {perform, {integer, Button} {string, "setTitle:"}, {string, "click me"}}

Button is the integer in "Instance" above I assume

> receive
> ok
>
>
> Objective-C side
>
> On receiving {create_instance, {string, Clazz}}:
>
> // note that `Class' is a reserved word
> id instance = [[NSClassFromString(Clazz) alloc] init];
> if (instance) {

What is instance? is this "really" a 32 bit pointer?
How do I serialize it to send it back to erlang?


> reply {ok, instance};
> } else {
> reply {error, @"No such class"}
> }
>
> On receiving {perform, {integer, Instance}, {string, Selector}, {string,
> Object}}:
> SEL sel = NSSelectorFromString(Selector);
> if (sel) {
> if ([Instance respondsToSelector(sel)]) {
> [Instance performSelector:sel withObject:Object];
> reply ok;
> } else {
> reply {error, @"No such selector"};
> }
> } else {
> reply {error, @"Invalid selector"}
> }

Same question here. On the "wire" I'll see an encoding of
{perform, {integer, Instance}, ... and so on How do I make an Objective
C id or NSString from a sequence of bytes that I read from a socket.
Also do I have to worry about strings (for example) being garbage collected.

For example If I say (in objective C)

NSString s = @"hello"

I create a literal string in the variable s

But if I receive a string "hello" somewhere in a buffer from a socket
I need to create a NSString and put it somewhere so it doesn't get
garbage collected away. Something like:

NSMutableArray *stringtable = [[NSMutableArray alloc] init];

NSString s = [[NSString alloc] initWithString: Data]
[stringtable addObject:s];

(Pardon my Objective C here - I'm a total beginner here)

> This was a little messy, but hopefully you will get the idea.

Yes - I get the idea, the problem is the nitty gritty details, not the idea.
The idea is easy. Allocate some memory to store the stuff you received in
create some dynamic objects and call some methods - problem is how.

Thanks - I'll try this later

/Joe

Gianfranco Alongi

unread,
Jul 18, 2012, 8:29:23 AM7/18/12
to Joe Armstrong, erlang-q...@erlang.org
The Objective C mailing list is that way -->
https://lists.apple.com/mailman/listinfo/objc-language

Cheers

Dmitry Klionsky

unread,
Jul 18, 2012, 9:00:15 AM7/18/12
to Dmitry Klionsky, erlang-q...@erlang.org
Answers inlined.

On Wed, Jul 18, 2012 at 12:07 PM, Dmitry Klionsky
<dm.kl...@gmail.com> wrote:
>> > Decided to help you a little further:

>> Thanks - I appreciate this ...
>> I have a few more questions (inline)

>> >
>> > The problem is you can't just send("button", ...), because the "button" is
>> > not a symbol, but a NSButton's class (or something like this) instance.
>> > I'm not sure because I've never done any MacOX programming, but iOS.
>> > And in order to send a message to an instance you need to know it. So, in
>> > general, your workflow should be like this:
>> >
>> > Erlang side:
>> > %% create button
>> > send
>> > {create_instance, {string, "NSButton"}}
>> > receive
>> > {ok, Instance}

>> question 1:
>> Is Instance an integer here? (see question 3)

Yes, see below.

>> >
>> > %% set button's title
>> > send
>> > {perform, {integer, Button} {string, "setTitle:"}, {string, "click me"}}

>> Button is the integer in "Instance" above I assume

Right. Typo :(

>> > receive
>> > ok
>> >
>> >
>> > Objective-C side
>> >
>> > On receiving {create_instance, {string, Clazz}}:
>> >
>> > // note that `Class' is a reserved word
>> > id instance = [[NSClassFromString(Clazz) alloc] init];
>> > if (instance) {

>> What is instance? is this "really" a 32 bit pointer?
>> How do I serialize it to send it back to erlang?

Yes, it's a 32 or 64 bit pointer depending on the machine.
I guess you can use any method as long as serialization/deserialization
sequence gives the original value.

>> > reply {ok, instance};
>> > } else {
>> > reply {error, @"No such class"}
>> > }
>> >
>> > On receiving {perform, {integer, Instance}, {string, Selector}, {string,
>> > Object}}:
>> > SEL sel = NSSelectorFromString(Selector);
>> > if (sel) {
>> > if ([Instance respondsToSelector(sel)]) {
>> > [Instance performSelector:sel withObject:Object];
>> > reply ok;
>> > } else {
>> > reply {error, @"No such selector"};
>> > }
>> > } else {
>> > reply {error, @"Invalid selector"}
>> > }

>> Same question here. On the "wire" I'll see an encoding of
>> {perform, {integer, Instance}, ... and so on How do I make an Objective
>> C id or NSString from a sequence of bytes that I read from a socket.

>> Also do I have to worry about strings (for example) being garbage
collected.

>> For example If I say (in objective C)

>> NSString s = @"hello"

>> I create a literal string in the variable s

>> But if I receive a string "hello" somewhere in a buffer from a socket
>> I need to create a NSString and put it somewhere so it doesn't get
>> garbage collected away. Something like:

>> NSMutableArray *stringtable = [[NSMutableArray alloc] init];

>> NSString s = [[NSString alloc] initWithString: Data]
>> [stringtable addObject:s];

>> (Pardon my Objective C here - I'm a total beginner here)

For id see above, just make sure you restore the same value you got from
the `id instance = [[NSClassFromString(Clazz) alloc] init]' call.
The `instance' is just a pointer, so I'm pretty sure this will work.

Regarding the strings. You receive an array of bytes and it's possible
to build an NSString object out of them, like this:

char array[5] = {'a', 'b', 'c', 'd', '\0'};
NSString *string = [NSString stringWithCString:array
encoding:NSASCIIStringEncoding];

Also as long as you create an NSString object and pass it as a param to
a method you don't need to worry about the string being garbage collected.

>> > This was a little messy, but hopefully you will get the idea.

>> Yes - I get the idea, the problem is the nitty gritty details, not
>> the idea.
>> The idea is easy. Allocate some memory to store the stuff you
received in
>> create some dynamic objects and call some methods - problem is how.

>> Thanks - I'll try this later

>> /Joe

Hope this helps :)
Reply all
Reply to author
Forward
0 new messages