CライブラリとRuby間でバイナリデータのやりとり
色々あって、CでRubyのライブラリを作成中。
http://www.loveruby.net/w/RubyExtensionProgrammingGuide.htmlを参考にしています。
まあ基本は上記サイトとか,Rubyに付属のREADME.EXT.jaを見れば大体分かる。
でタイトルの件だけど、今まで不思議だったのは、
例えばTCPとか、バイナリデータが書いてあるファイルを読み込むとStringで取得できる。
このデータをライブラリ側に渡して、ライブラリ側で正しく読むには、
memcpy()を使えばいい。
とりあえず簡単なサンプル。
「file」というファイルにstruct test_tのデータをあらかじめ作っておく。
#include <stdio.h> #include <string.h> #include <ruby.h> struct test_t{ int a; int b; }; VALUE test_hoge(VALUE self, VALUE str){ struct test_t data; StringValue(str); memcpy(&data, RSTRING(str)->ptr, RSTRING(str)->len); printf("a:%d b:%d\n", data.a, data.b); return Qnil; } void Init_test(void){ VALUE test; test = rb_define_class("Test", rb_cObject); rb_define_method(test, "hoge", test_hoge, 1); }
ライブラリを使う側。
#!/usr/bin/env ruby require 'test.so' str = File.read("file") test = Test.new test.hoge(str)
これで問題無しに読み込める。
結局、Cで型が分からない場合は文字列で保存するしかない。
でFileだろうが、TCPだろうがCレベルでは文字列(char)として持っていて、
それをRuby側でみるとString型なのでpとかで出力すると、
それぞれに対応したASCIIとして出力されるみたい。