是否有一些关于如何在Go中编写Ruby扩展的教程或实践课程?
答案 0 :(得分:69)
Go 1.5增加了对构建可从C调用的共享库的支持(因此可以通过FFI从Ruby调用)。这使得该过程比1.5版之前的版本更容易(当需要编写C粘合层时),并且Go运行时现在可以使用,这使得它在现实生活中真正有用(goroutines和内存分配之前是不可能的,因为它们需要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
答案 1 :(得分:11)
通常情况下,我会尝试给你一个直接的答案,但到目前为止的评论显示可能没有。所以,希望这个通用解决方案和其他一些可能性的答案是可以接受的。
一个通用解决方案:将高级语言程序编译到可从C调用的库中。为Ruby编译。在这一点上,必须非常小心集成。这个技巧是过去整合多种语言的好方法,通常是出于遗留原因。事实上,我不是Go开发人员,我不知道你可以编译Go进入可以从C调用的东西。继续。
创建两个独立程序:Ruby和Go程序。在程序中,使用一种非常有效的来回传递数据的方法。扩展将简单地建立与Go程序的连接,发送数据,等待结果,并将结果传递回Ruby。通信通道可能是OS IPC,套接字等。无论每个支持什么。如果没有安全问题并且您使用预定义的消息格式,则数据格式可以非常简单。这进一步提高了速度。我的一些旧程序使用XDR作为二进制格式。现在,人们似乎使用JSON,Protocol Buffers和ZeroMQ样式的线协议之类的东西。
第二个建议的变化:使用ZeroMQ!或类似的东西。 ZeroMQ快速,强大,并且具有两种语言的绑定。它为您管理整个上段。缺点是它在性能调整方面不够灵活,并且有额外的东西你不需要。
使用两个进程并在它们之间传递数据的棘手部分是速度惩罚。离开Ruby可能不合理。但是,Go具有出色的本机性能和并发特性,可以证明编写应用程序的一部分是合理的,而不是像Ruby这样的脚本语言。 (可能是你提出问题的理由之一。)所以,试试这些策略。如果您的工作程序也更快,请使用它。否则,坚持使用Ruby。
可能不太吸引人的选择:使用具有类似优势的Go之外的其他东西,允许从C调用,并且可以集成。虽然它不是很受欢迎,Ada是一种可能性。它在本机代码,(受限制的)并发性,可靠性,低级支持,跨语言开发和IDE(GNAT)方面一直很强大。此外,Julia是高性能技术和并行编程的新语言,可以编译成可从C调用的库。它也有一个JIT。也许从Ruby + Go到Ruby +(更合适的语言)改变问题陈述会解决问题吗?
答案 2 :(得分:4)
从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/)