在Go中编写Ruby扩展(golang)

时间:2013-04-08 13:12:08

标签: ruby rubygems gem go

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

3 个答案:

答案 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/