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?
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.
One way is Theo's way with NSTask, NSPipe and NSFileHandle. You can start by looking at the code to CouchDBX http://couchprojects.googlecode.com/svn/trunk/unofficial-binary-releases/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?
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.
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:
http://muvara.org/crs4/erlang/ffi
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With