web-dev-qa-db-ja.com

Go(golang)でRuby拡張子を書く

GoでRubyの拡張機能を作成する方法に関するチュートリアルや実践的なレッスンはありますか?

37

Go 1.5では、Cから(したがって、FFI経由でRuby)から呼び出し可能な共有ライブラリを構築するためのサポートが追加されました。これにより、1.5より前のリリースよりもプロセスが簡単になります( Cグルーレイヤー)、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 
71

通常、私はあなたに正直な答えを与えるように努めますが、これまでのコメントはそれがないかもしれないことを示しています。したがって、一般的な解決策と他のいくつかの可能性を備えたこの答えが受け入れられることを願っています。

1つの一般的な解決策:高級言語プログラムをCから呼び出し可能なライブラリにコンパイルします。Ruby用にラップします。この時点では、統合について非常に注意する必要があります。このトリックは、通常はレガシーの理由で、過去に多くの言語を統合するための素晴らしい応急修理でした。私はGo開発者ではないので、GoをCから呼び出し可能なものにコンパイルできるかどうかはわかりません。次に進みます。

2つのスタンドアロンプ​​ログラムを作成します:Ruby and Goプログラム。プログラムでは、非常に効率的な方法でデータをやり取りします。拡張機能は、Goプログラムへの接続を確立し、データを送信します。 、結果を待って、結果をRubyに返します。通信チャネルはOS IPC、ソケットなどです。それぞれがサポートするものは何でもかまいません。セキュリティの問題がなく、事前定義されたメッセージ形式を使用している場合、データ形式は非常に単純です。 。それはさらに速度を向上させます。私の古いプログラムのいくつかはバイナリ形式にXDRを使用していました。最近、人々はJSON、プロトコルバッファ、ZeroMQスタイルのワイヤプロトコルなどを使用しているようです。

2番目の提案のバリエーション:ZeroMQを使用してください!または同様のもの。 ZeroMQは高速で堅牢であり、両方の言語にバインドされています。それはあなたのために上記の段落全体を管理します。欠点は、パフォーマンスチューニングの柔軟性が低く、不要なものが余分にあることです。

2つのプロセスを使用し、それらの間でデータを渡す際の注意が必要なのは、速度の低下です。オーバーヘッドはRubyを離れることを正当化しないかもしれません。ただし、Goには、Rubyのようなスクリプト言語と比較して、アプリケーションのコーディング部分を正当化する可能性のある優れたネイティブパフォーマンスと同時実行機能があります。 (おそらくあなたの質問に対するあなたの正当化の1つです。)それで、これらの戦略のそれぞれを試してください。より高速なプログラムを入手した場合は、それを使用してください。それ以外の場合は、Rubyを使用してください。

おそらくあまり魅力的ではないオプション:同様の利点があり、Cからの呼び出しを可能にし、統合できるGo以外のものを使用します。あまり人気はありませんが、エイダは可能性があります。ネイティブコード、(制限された)同時実行性、信頼性、低レベルのサポート、言語間の開発、およびIDE(GNAT))に長い間強く取り組んできました。また、Juliaは高性能技術の新しい言語です。 Cから呼び出し可能なライブラリにコンパイルできる並列プログラミング。JITもあります。問題ステートメントをRuby + GoからRuby +(より適切な言語)に変更すると問題が解決するでしょうか。

11
Nick P

Go 1.5以降、共有ライブラリとCヘッダーファイルを出力するようにGoコンパイラに指示する新しいビルドモードがあります。

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

4