在Go中编写Ruby扩展(golang)

Dmi*_*kin 37 ruby gem rubygems go

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

Dar*_*tle 70

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
Run Code Online (Sandbox Code Playgroud)

请注意,//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)
Run Code Online (Sandbox Code Playgroud)

该库是用以下内容构建的:

go build -buildmode=c-shared -o goFuncs.so goFuncs.go
Run Code Online (Sandbox Code Playgroud)

运行Ruby脚本会产生:

42

  • 我完全按照你的例子去了Go 1.5,它就像一个魅力,对我来说没有段错误. (2认同)
  • 我不再得到段错误,旧的(1.5之前的)答案似乎不再相关,所以我更新了答案,更直接地回答了现代Go的问题.(目前使用Go 1.7和Ruby 2.3.1p112.) (2认同)

Nic*_*k P 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 +(更合适的语言)改变问题陈述会解决问题吗?