用Go编写Ruby扩展(golang)



关于如何在Go中编写Ruby扩展有一些教程或实践课程吗?

Go 1.5增加了对构建可从C调用的共享库的支持(因此可以通过FFI从Ruby调用)。这使得这个过程比之前的1.5版本更容易(当需要编写C粘合层时),并且Go运行时现在是可用的,这在现实生活中实际上是有用的(以前不可能实现Go例程和内存分配,因为它们需要Go运行时,如果Go不是主要入口点,这是不可用的)。

goFuncs.go:

package main
import "C"
//export GoAdd
func GoAdd(a, b C.int) C.int {
    return a + b
}
func main() {} // Required but ignored

注意,每个导出函数都需要//export GoAdd注释;export后的符号表示函数的导出方式。

goFromRuby.rb:

require 'ffi'
module GoFuncs
  extend FFI::Library
  ffi_lib './goFuncs.so'
  attach_function :GoAdd, [:int, :int], :int
end
puts GoFuncs.GoAdd(41, 1)

这个库是用:

go build -buildmode=c-shared -o goFuncs.so goFuncs.go

运行Ruby脚本产生:<>之前42

通常我会尽量给你一个直接的答案,但到目前为止的评论显示可能没有。所以,希望这个答案有一个通解和一些其他的可能性是可以接受的。

一个通用的解决方案:将高级语言程序编译成可从c调用的库。在这一点上,我们必须非常小心积分。这个技巧在过去是集成许多语言的一个很好的组合,通常是出于遗留原因。问题是,我不是一个Go开发者,我不知道你可以把Go编译成可以从c调用的东西。继续。创建两个独立的程序:Ruby和Go程序。在程序中,使用一种非常有效的方式来来回传递数据。扩展将简单地建立到Go程序的连接,发送数据,等待结果,并将结果传递回Ruby。通信通道可以是OS IPC、套接字等。无论它们各自支持什么。如果没有安全问题,并且使用预定义的消息格式,那么数据格式可以非常简单。这进一步提高了速度。我的一些旧程序使用XDR作为二进制格式。如今,人们似乎在使用JSON、协议缓冲区和ZeroMQ风格的连接协议。

第二个建议的变化:使用ZeroMQ!或者类似的东西。ZeroMQ快速、健壮,并且对两种语言都有绑定。它为你管理了上面的整个段落。缺点是它在性能调优方面不太灵活,并且有您不需要的额外内容。

使用两个进程并在它们之间传递数据的棘手部分是速度损失。开销可能不值得放弃Ruby。然而,Go具有出色的本地性能和并发特性,这可能比使用Ruby等脚本语言编写部分应用程序更合理。(这可能是你提出这个问题的理由之一。)所以,试试这些策略吧。如果你有一个工作的程序,也更快,使用它。否则,继续使用Ruby。

可能不太吸引人的选择:使用Go以外的具有类似优势的东西,允许从C调用,并且可以集成。虽然它不是很受欢迎,但Ada是一种可能性。长期以来,它在本地代码、(受限制的)并发性、可靠性、低级支持、跨语言开发和IDE (GNAT)方面一直很强大。此外,Julia是一种用于高性能技术和并行编程的新语言,可以编译成可从c调用的库。它也有JIT。也许将问题陈述从Ruby+Go改为Ruby+(更合适的语言)将解决问题?

从Go 1.5开始,有一个新的构建模式,告诉Go编译器输出一个共享库和一个C头文件:

-buildmode c-shared

(这在这个有用的教程中有更详细的解释:http://blog.ralch.com/tutorial/golang-sharing-libraries/)

使用新的构建模式,您不再需要自己编写C粘合层(正如之前的响应中所建议的那样)。一旦有了共享库和头文件,就可以继续使用FFI调用go创建的共享库(示例如下:https://www.amberbit.com/blog/2014/6/12/calling-c-cpp-from-ruby/)

最新更新