我有一个 Go 程序,出于效率原因,无法用 Common Lisp 重写。我如何通过 Common Lisp 运行它?
到目前为止的选项:
在我看来,使用外部函数接口是执行此操作的“正确”方法。然而我所做的研究却直接走进了死胡同。如果这是获胜者,有哪些资源可以学习如何与 Go 交互?
让 Go 程序一直运行,同时监听端口是可行的。如果这是最好的方法,我会继续努力使其发挥作用。
这似乎是错误的。
或者有什么我还没想到的很棒的方法吗?
这取决于你想做什么,但1-3都是可行的选择
要使其正常工作,您需要在 go 和 lisp 端都使用 FFI。 您需要将 Go 中的适当函数 extern 为 C 函数,然后使用 lisp 中的 cffi 调用它们。请参阅 https://golang.org/cmd/cgo/#hdr-C_references_to_Go 了解如何在 go 中 extern 函数。在这种情况下,您将创建一个动态可链接库(dll 或 so 文件)而不是可执行文件。
第二个选项是将 go 程序作为守护进程运行,并使用某种形式的 IPC(例如套接字)在 lisp 和 go 之间进行通信。如果你的程序长时间运行,或者如果有一个服务器和一个或多个客户端是有意义的(服务器可以很容易地是 lisp 代码,就像 go 代码一样),那么这种方法很有效。特别是套接字也更加灵活,您可以用其他语言编写组件或更改一个组件的语言,而无需更改其他组件,只要您维护相同的协议即可。此外,您还可以在单独的硬件上运行这些组件。但是,使用套接字可能会损害性能。 还有其他可用的 IPC 方法,例如 FIFO 文件(命名管道)、SHM 和消息队列,但它们比套接字更依赖于系统。
第三种方式是启动子进程。这是一个可行的选择,但有一些注意事项。首先,启动子进程的行为取决于 Lisp 实现和操作系统。 UIOP 消除了许多实现差异的细节,但有些细节太大而无法克服。特别是,根据实现的不同,您可能能够也可能无法并行运行子进程。如果没有,您每次想要与 go 通信时都必须运行单独的命令,这意味着每次需要时都要等待进程启动。您也可能或可能无法在启动子流程后向其发送输入。
另一种选择是运行命令来启动 go 进程,然后使用套接字或其他 IPC 与其通信,然后在关闭 lisp 程序之前运行命令来停止该进程。
就我个人而言,我认为使用套接字是最有吸引力的选择,但根据您的需求,其他选项之一可能更适合。
CFFI 是使用 Common Lisp 中的 C。这是一种获得新功能的简单方法,无需太多麻烦,因为现有的库通常是用 C 编写的或具有 C 接口。如果您可以从 Go 源代码创建一个 C 库,那么您可以这样做并使用 CL 的外部功能。
如果 Go 程序是一个应该提供某些东西的服务,那么Sockets(或其他双向通信总线)就很好。例如。服务 http 请求的应用程序服务器。通常,如果您只需要在每次运行 CL 程序时使用一次 go 程序,那么这不是正确的方法。
如果您可以使用参数运行应用程序并获得在 Common Lisp 中使用的结果,那么Subprocess 是最好的。如果你要多次使用 Go 程序,那就不好了,因为它会产生开销(其中套接字是最好的)
太棒了做到这一点的方法就是用 Common Lisp 来完成整个事情。如果您选择一个具有良好编译器的实现并且编写得很好,您可能就可以将应用程序作为 CL 映像。如果你需要加快速度,你可以专注于缓慢的部分并优化它们,你可以通过用 C 编写优化来使用 CFFI。甚至还有一个 Inline C for SBCL,你可以在你想要的地方编写 C在 CL 中进行优化,您不需要将优化编写在自己的文件中并单独编译和链接。