2012-03-08 15 views
6

私はmath.hを使用しているRubyのC拡張を書いています。 OSXとWindowsの両方でコンパイルされています。 Windowsでは、Visual Studio Express C++ 2010に付属のnmakeを使用します。Cで定義されていない関数を定義するには?

math.hには、VSにround()関数が含まれていませんでした。だから私は補うためにこれを追加しました:

static inline double round(double value) 
{  
    return floor(value + 0.5); 
} 

そこが定義されているround()としてOSXの下でコンパイルするときにコースを外れ、エラーの原因となりました。 (私が思う実際のエラーは、それがすでに非静的バージョンと宣言されていた後、私は私が静的宣言のだということでした。

かかわらず、私はそれが存在しない場合、この関数を再定義しないようにしたいと思います。

で。私は、これは条件付きの持っている瞬間:?私のシナリオで働いていた

#ifdef _WIN32 
static inline double round(double value) 
{  
    return floor(value + 0.5); 
} 
#endif 

- しかし、それは少し一般的なようで、私が意味する、私はWindowsで別のコンパイラでコンパイルした場合にどのような

だから私の質問は、関数が既に定義されているかどうかを検出できますか?自分でそれを定義しないでください?

かは、私が特にコンパイラnmake使用を検出することができます - 私はそれだと思うcl

私はそれが最も堅牢な方法のように見えるように私は、理想的には、関数がすでに定義されているかどうかを検出することができるだろうと思っています。しかし、それは少し一般的なようだ - 私のシナリオで働いていた

答えて

0

私はRubyのmkmfはユーティリティは、1が機能の存在を確認するために使用できる方法have_funcを持っていることがわかった:http://apidock.com/ruby/Object/have_func

私はその後、私のHAVE_ROUNDプリプロセッサ定数を与えた私のextconf.rbファイルにhave_func('round', 'math.h')を追加しました。

その後、私は安全に(ラウンド定義することができます)私自身は、それが存在していなかったそれ:

#ifndef HAVE_ROUND 
static inline double round(double value) 
{  
    return floor(value + 0.5); 
} 
#endif 

は完全に働きました! :)

2

。つまり、Windows上で別のコンパイラでコンパイルすればどうなるでしょうか?

  1. 一般的です。
  2. どのコンパイラを使用するかは関係ありません。シンボルが定義されているかどうかを確認するだけです。任意のコンパイラを使用してそのシンボルを定義できますが、それは重要ではありません。 ifdefは、通常、移植性の問題をどのように処理するかです。
  3. roundはC99標準で定義されています。 VSは現時点でC99をサポートしていないので、それが欠落しています。あなたが何をしたか
+0

私が懸念していたのは、例えば私がVisual Studioを更新し、 'math.h'に' round() 'を含めた場合、OSXのような競合が発生するということでした。だから私は環境の代わりに機能をチェックする方が良い考えだと思っていたのです。これは、ユーザーエージェントの文字列を盗聴するのではなく、機能をテストするウェブ開発の考え方です。 – thomthom

+0

@thomthom:ええ、でもこれはウェブ開発=)。これは、一般的なやり方です。コンパイラを変更するとブレークして修正する必要がありますが、ほとんどの場合は避けることができます。この場合、C99に 'round 'が追加されました。 VSはC99をサポートしていないため、C99は存在しません。 –

+0

GNUのautoconfは、機能ベースのアプローチを使用して、#HAVE_featureという形式の定数を定義しています。例えば、あなたは 'HAVE_ROUND'を定義するかもしれません。この場合はコンパイラに依存するため、コンパイルコマンドのCプリプロセッサ定義で "-DHAVE_ROUND = 0"を実行できます。 round()を持つコンパイラの下では未定義のままにしておきます。 round()関数のラッパーは、#if defined(HAVE_ROUND)&&!HAVE_ROUND ... function declaration ... #endif'を読み込みます。 –

0

非互換性に対処するための正しい方法です。

システムに依存しない非互換性を扱うこの方法は「一般的ではありませんが、そのような問題を抽象化するJAVAのような言語とは逆です。一方、プラットフォームが提供する最高のパフォーマンスを常に得ることができます。

関連する問題