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?
我正在探索在Erlang中编写应用程序的可能性,但它需要有一部分用Cocoa编写(可能是Objective-C)。我希望前端和后端能够轻松地进行通信。怎么能做到最好?
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?
我可以考虑使用C端口和连接进程,但我认为我想要一个相反的情况(前端启动并连接到后端)。有命名管道(FIFO),或者我可以通过TCP端口或命名的BSD套接字使用网络通信。有没有人有这方面的经验?
6 个解决方案
#1
10
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.
一种方法是让应用程序的Erlang核心成为Cocoa前端使用您设计的一些简单协议通过Unix域套接字进行通信的守护进程。
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).
使用Unix域套接字意味着可以通过launchd按需启动Erlang守护进程,并且Cocoa前端可以通过环境变量找到要使用的套接字的路径。这使得应用程序和守护进程之间的集合变得微不足道,并且它还使得开发多个前端(或者可能是包含与守护进程的通信的框架)变得简单。
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.
Mac OS X launchd系统非常酷。如果您指定应通过安全的Unix域套接字按需启动作业,则launchd将实际创建具有适当权限的套接字本身,并通过作业属性列表中指定的环境变量公布其位置。作业在启动时,实际上会在执行简单签入时通过launchd将文件描述符传递给套接字。
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.
最终这意味着前端的整个过程打开套接字以与守护进程通信,启动守护进程启动,并且响应通信的守护进程可以是安全的,即使前端和守护进程以不同的权限运行水平。
#2
2
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/
一种方式是Theo使用NSTask,NSPipe和NSFileHandle的方式。您可以从查看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?
有什么理由说明为什么这种沟通不能简单地用mochiweb和json通信来处理?
#3
1
Usually when creating Cocoa applications that front UNIX commands or other headless programs you use an NSTask
:
通常在创建前端UNIX命令或其他无头程序的Cocoa应用程序时,您使用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.
使用NSTask类,您的程序可以作为子进程运行另一个程序,并可以监视该程序的执行。 NSTask对象创建一个单独的可执行实体;它与NSThread的不同之处在于它不会与创建它的进程共享内存空间。
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.
任务在由若干项的当前值定义的环境中运行:当前目录,标准输入,标准输出,标准错误以及任何环境变量的值。默认情况下,NSTask对象从启动它的进程继承其环境。如果任务的任何值应该不同,例如,如果当前目录应该更改,则必须在启动任务之前更改该值。任务的环境在运行时无法更改。
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).
您可以通过stdin / stdout / stderr与后端进程通信。基本上NSTask是exec(或者fork或system,我总是忘记区别)的高级包装器。
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.
据我所知,你不希望Erland程序成为一个持续运行的后台守护程序,但是如果你这样做,请按照@Chris的建议去做。
#4
1
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:
NSTask和Unix域套接字方法都是很好的建议。需要关注的是正在开发的Erlang FFI实现:
http://muvara.org/crs4/erlang/ffi
http://muvara.org/crs4/erlang/ffi
#5
1
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.
erl_call应该可以在NSTask中使用。我在Textmate命令中使用它,速度非常快。将erl_call与OTP gen_server结合使用可以让您相对轻松地保持持久的后端状态。有关详细信息,请参阅我在博客上关于erl_call的帖子。
#6
1
Using NSTask you may also consider using PseudoTTY.app (which allows interactive communication)!
使用NSTask你也可以考虑使用PseudoTTY.app(允许交互式通信)!
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.
另一个感兴趣的示例代码可能是BigSQL,一个PostgreSQL客户端,它允许用户将SQL发送到服务器并显示结果。
open -a Safari http://web.archive.org/web/20080324145441/http://www.bignerdranch.com/applications.shtml
#1
10
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.
一种方法是让应用程序的Erlang核心成为Cocoa前端使用您设计的一些简单协议通过Unix域套接字进行通信的守护进程。
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).
使用Unix域套接字意味着可以通过launchd按需启动Erlang守护进程,并且Cocoa前端可以通过环境变量找到要使用的套接字的路径。这使得应用程序和守护进程之间的集合变得微不足道,并且它还使得开发多个前端(或者可能是包含与守护进程的通信的框架)变得简单。
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.
Mac OS X launchd系统非常酷。如果您指定应通过安全的Unix域套接字按需启动作业,则launchd将实际创建具有适当权限的套接字本身,并通过作业属性列表中指定的环境变量公布其位置。作业在启动时,实际上会在执行简单签入时通过launchd将文件描述符传递给套接字。
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.
最终这意味着前端的整个过程打开套接字以与守护进程通信,启动守护进程启动,并且响应通信的守护进程可以是安全的,即使前端和守护进程以不同的权限运行水平。
#2
2
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/
一种方式是Theo使用NSTask,NSPipe和NSFileHandle的方式。您可以从查看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?
有什么理由说明为什么这种沟通不能简单地用mochiweb和json通信来处理?
#3
1
Usually when creating Cocoa applications that front UNIX commands or other headless programs you use an NSTask
:
通常在创建前端UNIX命令或其他无头程序的Cocoa应用程序时,您使用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.
使用NSTask类,您的程序可以作为子进程运行另一个程序,并可以监视该程序的执行。 NSTask对象创建一个单独的可执行实体;它与NSThread的不同之处在于它不会与创建它的进程共享内存空间。
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.
任务在由若干项的当前值定义的环境中运行:当前目录,标准输入,标准输出,标准错误以及任何环境变量的值。默认情况下,NSTask对象从启动它的进程继承其环境。如果任务的任何值应该不同,例如,如果当前目录应该更改,则必须在启动任务之前更改该值。任务的环境在运行时无法更改。
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).
您可以通过stdin / stdout / stderr与后端进程通信。基本上NSTask是exec(或者fork或system,我总是忘记区别)的高级包装器。
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.
据我所知,你不希望Erland程序成为一个持续运行的后台守护程序,但是如果你这样做,请按照@Chris的建议去做。
#4
1
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:
NSTask和Unix域套接字方法都是很好的建议。需要关注的是正在开发的Erlang FFI实现:
http://muvara.org/crs4/erlang/ffi
http://muvara.org/crs4/erlang/ffi
#5
1
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.
erl_call应该可以在NSTask中使用。我在Textmate命令中使用它,速度非常快。将erl_call与OTP gen_server结合使用可以让您相对轻松地保持持久的后端状态。有关详细信息,请参阅我在博客上关于erl_call的帖子。
#6
1
Using NSTask you may also consider using PseudoTTY.app (which allows interactive communication)!
使用NSTask你也可以考虑使用PseudoTTY.app(允许交互式通信)!
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.
另一个感兴趣的示例代码可能是BigSQL,一个PostgreSQL客户端,它允许用户将SQL发送到服务器并显示结果。
open -a Safari http://web.archive.org/web/20080324145441/http://www.bignerdranch.com/applications.shtml