use*_*167 5 c++ sockets rpc xml-rpc common-lisp
我有两个代码库:一个用C++编写,另一个用Common Lisp编写.在Lisp代码库中实现了一个特殊的功能,我想从我的C++代码中访问它.我搜索了外部函数接口来从C++调用Lisp函数,但似乎找不到任何东西(我发现其他方向的FFI主要是).所以我决定实现符合我要求的某种形式的RPC,它们是:
这两个代码都将在同一台机器上运行,因此远程机器调用的可扩展性并不重要.
来自C++的输入将是一个Lisp风格的列表,这是Lisp代码中的函数将作为输入.
每次执行代码时,此调用将进行1000次,因此每次远程调用的性能至关重要.
到目前为止,我从网上的各种资源中了解到可能的解决方案是:
套接字 - 设置Lisp代码的实例,该代码将侦听来自C++代码的函数调用,在给定输入上运行函数,并将结果返回给C++代码.
XML-RPC - 在Lisp端设置XML-RPC服务器(这很容易,因为我使用Allegro Common Lisp,它提供了支持XML-RPC的API),然后使用许多XML-RPC库中的一个用于C++进行客户端呼叫.
我用这些方法看到的利弊似乎如下:
套接字是一个低级构造,因此看起来我需要自己完成大部分连接管理,读取和解析套接字上的数据等.
XML-RPC似乎更适合我的需求,但我读到它总是使用HTTP,并且没有办法使用UNIX域套接字.因此,感觉XML-RPC可能对我的想法有些过分.
有没有人有任何实现类似代码集成的经验?本地RPC的套接字和XML-RPC之间的性能是否存在显着差异?任何关于哪种方法可能更好的建议都会非常有帮助.此外,还将赞赏关于不同技术的建议.
编辑:以下是有关共享功能的更多详细信息.在Lisp代码中有一个函数f(它很复杂,足以使C++中的重新实现成本过高).它将两个列表L1和L2作为输入.我如何设想这种情况如下:
L1和L2的大小通常不大:
L1是通常包含100个元素的列表,每个元素是最多3-4个原子的列表.
L2也是包含<10个元素的列表,每个元素是最多3-4个原子的列表.
因此,每个RPC的总数据量可能是100s/1000s字节的字符串.这个调用是在我的C++代码中的每个while循环开始时进行的,因此很难给出每秒调用次数的具体数字.但是根据我的实验,我可以说它通常每秒完成10s-100s.f不是数值计算:它的象征性.如果你熟悉AI,它本质上是在一阶逻辑中进行符号统一.所以它没有副作用.
如果你看一些Common Lisp实现,他们的FFI允许从C端调用Lisp.那不是遥远的,而是本地的.有时直接包含Lisp是有意义的,而不是远程调用它.
像LispWorks或Allegro CL这样的商业Lisps也可以提供共享库,您可以从应用程序代码中使用它们.
例如,define-foreign-callable允许调用 LispWorks函数.
Franz ACL可以做到:http://www.franz.com/support/documentation/9.0/doc/foreign-functions.htm#lisp-from-c-1
ECL也应该可以在C方面使用.
还有许多其他方法可以使两个进程进行通信。您可以阅读进程间通信维基页面。
参数之一是异步或同步字符。您的远程处理是远程过程调用(来自客户端的每个请求都有来自服务器的一个响应)还是异步消息传递(双方都在发送消息,但没有请求和响应的概念;每一方都将传入消息处理为事件)。
另一个参数是延迟和带宽,即交换的数据量(每条消息,例如每秒)。
即使在同一台机器上,带宽也很重要。当然,管道或 Unix 套接字可以为您提供非常大的带宽,例如 100 兆字节/秒。但在某些情况下,这可能还不够。在这种管道情况下,数据通常从内存复制(通常两次)到内存(例如,从一个进程地址空间复制到另一个进程地址空间)。
但是您可能会考虑例如CORBA(请参阅lisp 方面的CLORB以及有关 OmniORB 的本教程)、RPC/XDR 或 XML-RPC(使用S-XML-RPC)在 lisp 端 )或JSON-RPC等。 ..
如果您没有大量数据和大量带宽(或每秒有很多请求或消息),我建议使用文本协议(可能使用 JSON、YAML 或 XML进行序列化),因为它比二进制更容易协议(BSON、protobuf等...)
套接字层(可以使用unix(7) AF_UNIX
套接字、普通匿名或命名管道(7) -s 或tcp(7)即 TCP/IP,其优点是使您能够将计算分布在两台机器上通过网络进行通信)可能是最简单的,只要你在(C++和Lisp)双方都有一个像这样的多路复用系统调用poll(2)这样的多路复用系统调用。您需要在两侧缓冲消息。
也许你想要MPI(带有在 lisp 端使用CL-MPI )。
我们无法为您提供更多帮助,除非您非常详细地解释从 C++ 到 Lisp 共享的“功能”是什么(它在做什么、每秒有多少个远程调用、什么数量和种类)数据,计算时间等......)。远程函数调用是幂等还是无效,有副作用吗?是不是一个无状态协议吗...
远程过程调用中涉及的实际数据类型非常重要:序列化具有共享节点的复杂[数学]循环图比简单的人类可读字符串要昂贵得多......
鉴于您的最新详细信息,我建议使用 JSON...它非常适合传输抽象语法树之类的数据。或者,仅传输 s 表达式(您可能会遇到 C++ 中解析它们的小问题,一旦您指定并记录了您的约定,这真的很容易;如果您的叶或符号名称具有任意字符,您只需定义一个对它们进行编码的约定。)。