Common lisp 如何从Common Lisp调用Go程序

Common lisp 如何从Common Lisp调用Go程序,common-lisp,Common Lisp,我有一个Go程序,由于效率原因不能用CommonLisp重写。如何通过Common Lisp运行它 迄今为止的选择: 1.CFFI 在我看来,使用外部功能界面似乎是做到这一点的“正确”方法。然而,我所做的研究直接导致了一条死胡同。如果这是赢家,有哪些资源可以学习如何与Go交互 2.插座 让Go程序在监听端口的同时一直运行是可行的。如果这是最好的方法,我会继续努力让它发挥作用 3.执行系统命令 这似乎是完全错误的 4.不为人知 还是有一种我还没有想到的很棒的方式?这取决于你想做什么,但1-3都是可

我有一个Go程序,由于效率原因不能用CommonLisp重写。如何通过Common Lisp运行它

迄今为止的选择:

1.CFFI 在我看来,使用外部功能界面似乎是做到这一点的“正确”方法。然而,我所做的研究直接导致了一条死胡同。如果这是赢家,有哪些资源可以学习如何与Go交互

2.插座 让Go程序在监听端口的同时一直运行是可行的。如果这是最好的方法,我会继续努力让它发挥作用

3.执行系统命令 这似乎是完全错误的

4.不为人知
还是有一种我还没有想到的很棒的方式?

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

1.CFFI 要使其正常工作,您需要在go和lisp端都使用FFI。 您需要将Go中的适当函数作为C函数进行外部化,然后使用lisp中的cffi调用它们。请参见如何在go中扩展函数。在这种情况下,您将创建一个动态链接库(dll或其他文件),而不是一个可执行文件

2.插座(IPC) 第二个选项是作为守护进程运行go程序,并使用某种形式的IPC(如套接字)在lisp和go之间进行通信。如果您的程序长时间运行,或者有一个服务器和一个或多个客户机(服务器可以像go代码一样轻松地成为lisp代码)是有意义的,那么这种方法很有效。socket尤其灵活,您可以使用其他语言编写组件或更改某个组件的语言,而无需更改其他组件,只要您维护相同的协议。此外,您还可以在单独的硬件上运行组件。但是,使用套接字可能会影响性能。 还有其他可用的IPC方法,如FIFO文件(命名管道)、SHM和消息队列,但它们比套接字更依赖于系统

3.系统命令(子进程) 第三种方法是启动子流程。这是一个可行的选择,但也有一些警告。首先,启动子进程的行为取决于lisp实现和操作系统。UIOP消除了实现差异的许多细节,但有些细节太大而无法克服。特别是,根据实现的不同,您可能无法并行运行子流程。如果没有,那么每次您想要与go通信时都必须运行一个单独的命令,这意味着每次需要时都要等待进程启动。启动子流程后,您可能也可能无法向其发送输入

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


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

CFFI是使用Common Lisp中的C。这是一种轻松获取新特性的方法,而不需要太多麻烦,因为库通常是用C编写的,或者有一个C接口。如果您可以从Go源代码创建一个C库,那么您可以这样做,并使用CL中的外来特性

插座(或其他双向通信总线)很好,因为Go程序是一种应该提供某种功能的服务。一个服务http请求的应用服务器。通常情况下,如果每次运行CL程序时只需要使用go程序一次,那么这不是正确的方法

如果您可以使用参数运行应用程序并获得在Common Lisp中使用的结果,那么子过程是最好的。如果你要多次使用Go程序,这是不好的,因为它会有开销(其中套接字的效果最好)


太棒了实现这一点的方法是用通用的Lisp语言完成整个过程。如果您选择了一个具有良好编译器的实现,并且编写得很好,那么您可能不会将应用程序作为CL映像。如果你需要加快速度,你可以把重点放在速度慢的部分并对其进行优化,你可以使用CFFI用C编写优化。甚至有一种方法,你可以只编写C,在其中你想在CL中进行优化,而不需要在自己的文件中编写优化并分别编译和链接。

选项(3)这是我一开始可能会选择的。但不知道你的要求,不清楚为什么会有“各种各样的错误”。这不是一个很有根据的观点。使用PHP的糟糕经历让我口齿不清。它在名单上!获胜者?在这个问题上多了解一些信息会很好:你用1击中了什么死胡同?为什么你觉得3是错的?它运行在什么操作系统/平台上?每个流程的寿命有多长?你会给go打一次电话,还是多次?诸如此类的事情。。。另外,我对效率声明有点怀疑,除非你指的是程序员时间/精力的效率,这似乎更合理,尽管。。。无论如何,我愿意认为这是理所当然的,但我不确定你是否应该。:)所有的问题都很好。我的印象是FFI适用于所有语言,而不仅仅是C语言。使用shell执行命令是一个太多的安全隐患。系统正在运行CentOS和SBCL。Lisp是作为守护进程运行的,如果需要,Go可以选择任何一种方式。Go程序需要从Lisp中多次调用,并在完成时响应。我用Lisp和Go写了同样的代码-每一个都花了同样多的精力(Lisp更漂亮;)-未优化的Lisp 65秒,优化的13.5秒-Go 2秒(字面意思)。对于那些偶然发现这个问题的解决方案的人来说,对我来说效果最好的解决方案是使用。它不是ANSI标准的一部分,所以请检查您的实现。对你的犹豫