I'm exploring the possibility of writing an application in Erlang, but it would need to have a portion written in Cocoa (presumably Objective-C). I'd like the front-end and back-end to be able to communicate easily. How can this best be done?

I can think of using C ports and connected processes, but I think I'd like a reverse situation (the front-end starting and connecting to the back-end). There are named pipes (FIFOs), or I could use network communications over a TCP port or a named BSD socket. Does anyone have experience in this area?

+9  A: 

One way would be to have the Erlang core of the application be a daemon that the Cocoa front-end communicates with over a Unix-domain socket using some simple protocol you devise.

The use of a Unix-domain socket means that the Erlang daemon could be launched on-demand by launchd and the Cocoa front-end could find the path to the socket to use via an environment variable. That makes the rendezvous between the app and the daemon trivial, and it also makes it straightforward to develop multiple front-ends (or possibly a framework that wraps communication with the daemon).

The Mac OS X launchd system is really cool this way. If you specify that a job should be launched on-demand via a secure Unix-domain socket, launchd will actually create the socket itself with appropriate permissions, and advertise its location via the environment variable named in the job's property list. The job, when started, will actually be passed a file descriptor to the socket by launchd when it does a simple check-in.

Ultimately this means that the entire process of the front-end opening the socket to communicate with the daemon, launchd launching the daemon, and the daemon responding to the communication can be secure, even if the front-end and the daemon run at different privilege levels.

Chris Hanson
+1  A: 

Usually when creating Cocoa applications that front UNIX commands or other headless programs you use an NSTask:

Using the NSTask class, your program can run another program as a subprocess and can monitor that program’s execution. An NSTask object creates a separate executable entity; it differs from NSThread in that it does not share memory space with the process that creates it.

A task operates within an environment defined by the current values for several items: the current directory, standard input, standard output, standard error, and the values of any environment variables. By default, an NSTask object inherits its environment from the process that launches it. If there are any values that should be different for the task, for example, if the current directory should change, you must change the value before you launch the task. A task’s environment cannot be changed while it is running.

You can communicate with the backend process by way of stdin/stdout/stderr. Bascially NSTask is a high-level wrapper around exec (or fork or system, I always forget the difference).

As I understand it you don't want the Erland program to be a background daemon that runs continuously, but if you do, go with @Chris's suggestion.

+2  A: 

One way is Theo's way with NSTask, NSPipe and NSFileHandle. You can start by looking at the code to CouchDBX

Ports are possible but not nice at all.

Is there some reason for why this communication can't simply be handled with mochiweb and json communication?

Jon Gretar
+1  A: 

The NSTask and Unix domain socket approaches are both great suggestions. Something to keep an eye on is an Erlang FFI implementation that's in the works:

+1  A: 

erl_call should be usable from an NSTask. I use it from a Textmate command and it is very fast. Combining erl_call with an OTP gen_server would let you keep a persistent backend state with relative ease. See my post on erl_call at my blog for more details.


Using NSTask you may also consider using (which allows interactive communication)!

Another sample code of interest could be BigSQL, a PostgreSQL client that enables the user to send SQL to a server and display the result.

open -a Safari