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