如何从Common Lisp调用Go程序

时间:2015-05-14 01:05:50

标签: common-lisp

我有一个Go程序,出于效率原因无法在Common Lisp中重写。如何通过Common Lisp运行它?

目前为止的选项:

1。 CFFI

在我看来,使用外部函数接口就像是“正确”的方法。然而,我所做的研究直接导致死路一条。如果这是胜利者,那么有哪些资源可以学习如何与Go进行交互?

2。套接字

在收听端口的同时让Go程序一直在运行。如果这是最好的方法,我会继续尝试让它发挥作用。

3。执行系统命令

这似乎有各种各样的错误。

4。未知

还是有一种我还没想过的很棒的方式吗?

2 个答案:

答案 0 :(得分:5)

这取决于你想做什么,但1-3都是可行的选择

1。 CFFI

要使其正常工作,您需要在go和lisp方面使用FFI。 您将需要从Go作为C函数extern相应的函数,然后使用来自lisp的cffi调用它们。请参阅https://golang.org/cmd/cgo/#hdr-C_references_to_Go,了解如何在go中使用extern功能。在这种情况下,您将创建一个动态可链接库(dll或so文件)而不是可执行文件。

2。套接字(IPC)

第二个选项是将go程序作为守护程序运行,并使用某种形式的IPC(如套接字)在lisp和go之间进行通信。如果您的程序长时间运行,或者如果有一个服务器和一个或多个客户端(服务器可以像转码一样容易成为lisp代码),这种方法很有效。特别是套接字也更灵活,您可以使用其他语言编写组件或更改一个组件的语言,而无需更改其他组件,只要您保持相同的协议即可。此外,您可以在单独的硬件上运行组件。但是,使用套接字可能会损害性能。 还有其他可用的IPC方法,例如FIFO文件(命名管道),SHM和消息队列,但它们比套接字更依赖于系统。

3。系统命令(子进程)

第三种方法是启动一个子流程。这是一个可行的选择,但它有一些警告。首先,启动子进程的行为取决于lisp实现和操作系统。 UIOP平滑了许多实现差异的细节,但有些太难以克服。特别是,根据实现,您可能或可能无法并行运行子进程。如果不是,则每次要与go通信时都必须运行单独的命令,这意味着每次需要时都要等待进程启动。启动后,您也可能或可能无法将输入发送到子进程。

另一种选择是运行命令以启动go进程,然后使用套接字或其他IPC与之通信,然后在关闭lisp程序之前运行命令以停止进程。

我个人认为使用套接字是最有吸引力的选择,但根据您的需要,其他选项可能更适合。

答案 1 :(得分:1)

CFFI 是使用Common Lisp中的C.这是一种简单的方法来获取新功能而不会有太多的麻烦,因为那里的库通常是用C语言编写的,或者有一个C接口。如果您可以从Go源创建C库,那么您可以执行此操作并使用CL中的外部功能。

套接字(或其他双向通信总线)很好,Go程序是一个应该提供某些功能的服务。例如。用于服务http请求的应用程序服务器。通常如果你只需要在每次运行CL程序时都使用go程序,这就不行了。

如果您可以使用参数运行应用程序并获得Common Lisp中使用的结果,那么

Subprosess 是最好的。如果你要多次使用Go程序会有好处,因为它会产生开销(插槽中的东西最好)

真棒这样做的方法是在Common Lisp 中制作整个内容。如果您选择具有良好编译器并且写得很好的实现,您可能会将应用程序作为CL映像。如果你需要加速你可以专注于缓慢的部分并优化它们,你可以通过在C中编写优化来使用 CFFI 。甚至有一个Inline C for SBCL你可以写C您希望在CL中进行优化,并且不需要在自己的文件中编写优化并单独编译和链接。