Ruby を書いていると、バイナリ処理を Go で書いて FFI 呼び出すことでいい感じにしたくなることがあります。
バイナリの受け渡しをする際は、String を使うと NULL 文字で終端されてしまう 1 ため、ポインタで渡してあげる必要があります。
C での書き方は ffi/ffi の wiki に載っていますが、Go での書き方は調べてもあまり出てこないので、ここに書いておきます。
main.go
package main
import (
"C"
"bytes"
"unsafe"
)
//export hoge
func hoge(pointer unsafe.Pointer, size C.int) *C.char {
// ポインタからバイト列を取り出す
var data []byte = C.GoBytes(pointer, size)
// バイト列を使って何か処理する
var result string = do_something(data)
// Go の string を C の string に変換して返す
return C.CString(result)
}
func do_something(data []byte) string {
return "xxx"
}
func main() {
}
hoge.rb
require 'ffi'
module Hoge
extend FFI::Library
# 上記の Go を shared library にコンパイルしたファイル
ffi_lib 'hoge.so'
attach_function :hoge, [:pointer, :uint], :string
class << self
# ポインタを渡す必要があるので private にしてインターフェイスを call_hoge に統一する
private :hoge
# 文字列をポインタに変換してから hoge を呼ぶ
def call_hoge(string)
mem_buf = FFI::MemoryPointer.from_string(string)
hoge(mem_buf, data.bytesize)
end
end
end
-
Binary data · ffi/ffi Wiki https://github.com/ffi/ffi/wiki/Binary-data ↩