2012-03-08 49 views
6

我寫在那裏我使用math.h Ruby的C擴展。它正在OSX和Windows上編譯。在Windows下,我使用了Visual Studio Express C++ 2010附帶的nmake如何在C中定義一個函數,如果它之前沒有定義過?

我發現VS在其math.h中沒有包含round()函數。所以我說這個補償:

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

這偏離航向OSX下編譯爲round()沒有被定義時導致了錯誤。 (實際的錯誤,我想我會宣佈我的是靜態的,它已經被宣佈非靜態版本之後。

無論如何,我想,以避免重新定義的函數,如果它確實存在。

在那一刻我有這樣的條件:?

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

,在我的情況下工作 - 但它似乎有點一般我的意思是,如果我編譯Windows下

所以我的問題是不同的編譯器,我可以檢測一個函數是否已經被定義,並且那麼避免自己定義它?

或者,我可以檢測具體的編譯器nmake使用 - cl我認爲這是什麼?

我想我最好能函數是否已經定義檢測,因爲它似乎是最可靠的方法。

回答

0

我發現Ruby的MKMF效用有一個方法have_func,人們可以用它來檢查的函數的存在:http://apidock.com/ruby/Object/have_func

我加have_func('round', 'math.h')extconf.rb文件,然後給了我一個HAVE_ROUND預處理器常量。

然後,我可以放心地定義圓()我自己也就不存在:

#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下有衝突。這就是爲什麼我認爲檢查功能而不是環境是一個更好的主意。這是我從web開發中進行思考的一個思路,您可以在其中測試功能而不是嗅探用戶代理字符串。 – thomthom 2012-03-08 21:22:05

+0

@ thomthom:是的,但這不是web開發=)。一般來說,你就是這樣做的。有時候當你改變編譯器的時候,事情就會崩潰,你需要修復它們,但是大部分情況下都可以避免它。在這種情況下,C99中增加了「round」。 VS不支持C99,這就是它不存在的原因。 – 2012-03-08 21:26:37

+0

GNU的autoconf使用基於特徵的方法,#定義形式爲'HAVE_feature'的常量。例如,你可以定義'HAVE_ROUND'。由於在這種情況下它依賴於編譯器,因此可以在編譯命令的C預處理器定義中執行「-DHAVE_ROUND = 0」。在具有round()的編譯器中將其保留爲undefined。 round()函數的包裝將讀取'#if defined(HAVE_ROUND)&&!HAVE_ROUND ...函數聲明...#endif'。 – 2012-03-09 05:09:00

0

你做了什麼處理的不兼容問題的正確方法。

你已經注意到,處理系統不兼容依賴這種方式是「不一般」,但相反像JAVA抽象,你必須處理這樣的事情等問題的語言。另一方面,您將始終獲得該平臺提供的最佳性能。

相關問題