chikuchikugonzalezの雑記帳

趣味とか日記とかメモとか(∩゚д゚)

Ruby2.0 (RubyInstaller版)で自前のC拡張がビルドできなかった問題について

まず結論から言うと、

  • RubyのC拡張をC++で書くとハマるぞ-( ゚д゚)
  • C++を使ってさらにC++0xとか使おうとするときは-std=c++0xじゃなくて-std=gnu++0xじゃないとハマるぞ-( ゚д゚)

です。

前提として次の環境でした。

  • Ruby2.0.0p0 (RubyInstaller版 32bit)
  • DevKitは DevKit-mingw64-32-4.7.2-20130224-1151-sfx の方

- 32bit/64bitで分けたらしい

  • C拡張はC++

- Rixmapのことです
- 無駄にC++0xを有効にしてました

この状態でextconfしてmakeしたら

In file included from E:/Ruby/Ruby200/include/ruby-2.0.0/ruby/defines.h:153:0,
                 from E:/Ruby/Ruby200/include/ruby-2.0.0/ruby/ruby.h:70,
                 from E:/Ruby/Ruby200/include/ruby-2.0.0/ruby.h:33,
                 from pcx.cxx:2:
E:/Ruby/Ruby200/include/ruby-2.0.0/ruby/win32.h: In function 'double rb_w32_pow(
double, double)':
E:/Ruby/Ruby200/include/ruby-2.0.0/ruby/win32.h:787:51: error: '_controlfp' was not declared in this scope
E:/Ruby/Ruby200/include/ruby-2.0.0/ruby/win32.h:788:16: error: '_PC_64' was not declared in this scope
E:/Ruby/Ruby200/include/ruby-2.0.0/ruby/win32.h:788:24: error: '_MCW_PC' was not declared in this scope

などと言われて ( ゚д゚) としてました*1

でまぁどうなってのかなって思ったら

#elif defined(__MINGW64_VERSION_MAJOR)
/*
 * Set floating point precision for pow() of mingw-w64 x86.
 * With default precision the result is not proper on WinXP.
 */
static inline double
rb_w32_pow(double x, double y)
{
    double r;
    unsigned int default_control = _controlfp(0, 0);
    _controlfp(_PC_64, _MCW_PC);
    r = pow(x, y);
    /* Restore setting */
    _controlfp(default_control, _MCW_PC);
    return r;
}
#endif

とかなってるわけですよ。これといっておかしいところはないと。
仕方ないんで_controlfpがドコに居るのかっていうのをぐーぐるさんに聞いたら float.h にいるとか言われたんで見てみたんですよ。そしたらですね。この_controlfpとかって__STRICT_ANSI__が定義されてると使えないってなってるじゃないですか。すごく怪しい。

んで、これが定義される条件を調べたらとりあえず

が付くと定義されるとかって見つかりまして。そして気になる記述がソコに

c99の場合は__STRICT_ANSI__が定義される

Memo/std=c99とstd=gnu99の違い - たむちょんの脳内図鑑
( ゚д゚)
(つд⊂)ゴシゴシ
( ゚д゚)

それで思い出しんたんですよね-、-std=gnu++0xの存在を

なんでc++0xを使うのに-std=c++0xと-std=gnu++0xがあるのかと思ってたんですが、規格に厳格かどうかっていうのが違ったのか-、っていう新しい発見でした。

…でもこれって、C99を指定するときに-std=c99してるC拡張がビルドできないっていう問題が出るんだけどどうなんだろコレ…

*1:Ruby1.9とかだとビルドできたのに