Ruby の拡張ライブラリ開発では RSTRING_PTR, RSTRING_LEN が 1.8.6 から使える

2007/06/14 10:33am

最近、Ruby の拡張ライブラリを書いている。

Ruby 1.9 からは ArrayString の短いものが struct RObject の構造体に埋め込まれるようになった。そのため、struct RString が変更されており、struct RString の C 文字列や文字(バイト)数にアクセスする従来の直接的な方法、

char *p  = RSTRING(s)->ptr;
long len = RSTRING(s)->len;

は 1.9 の環境ではコンパイルできなくなっている。

では、どうするか、というと、1.9 からは RSTRING_PTR, RSTRING_LEN というマクロをかましてアクセスする。

char *p = RSTRING_PTR(s);
long len = RSTRING_LEN(s);

実をいうと、1.9 向けの拡張ライブラリを書いてるわけではないので、ここからが本題。

この RSTRING_PTR, RSTRING_LEN、1.8.6 でも用意されていたりする。いまから、これらのマクロを使っておけば、1.9 への移行がすこしは楽になるかもしれない。

ruby.h

#define RSTRING_PTR(s) (RSTRING(s)->ptr)
#define RSTRING_LEN(s) (RSTRING(s)->len)

しかし、このままだと問題が残る。

というのも、1.8.5 以前のバージョンでは、依然、これらのマクロが利用できないからだ。なので、以下のように、#ifndef ディレクティブを使って対応するようにしている。

#ifndef RSTRING_PTR
#  define RSTRING_PTR(s) (RSTRING(s)->ptr)
#endif
#ifndef RSTRING_LEN
#  define RSTRING_LEN(s) (RSTRING(s)->len)
#endif

これで、1.8.6 以降では ruby.h のマクロが、それより前のバージョンでも独自に定義したマクロが使われるようになるというわけ。普段 1.8.6 で開発していて、1.8.5 な環境でコンパイルしようとして怒られたので、ブログに書いて残しておく。