2010-09-02 62 views
34

這是我第一次嘗試編寫任何在C++中稍微複雜的東西,我試圖構建一個共享庫,我可以從Objective-C和.NET應用程序(好吧,這部分是後話......)編寫跨平臺的C++代碼(Windows,Linux和Mac OSX)

我的代碼是 -

#ifdef TARGET_OS_MAC 
    // Mac Includes Here 
#endif 

#ifdef __linux__ 
    // Linux Includes Here 
    #error Can't be compiled on Linux yet 
#endif 

#ifdef _WIN32 || _WIN64 
    // Windows Includes Here 
    #error Can't be compiled on Windows yet 
#endif 

#include <iostream> 

using namespace std; 

bool probe(){ 
    #ifdef TARGET_OS_MAC 
    return probe_macosx(); 
    #endif 
    #ifdef __linux__ 
    return probe_linux(); 
    #endif 
    #ifdef _WIN32 || _WIN64 
    return probe_win(); 
    #endif 
} 

bool probe_win(){ 
    // Windows Probe Code Here 
    return true; 
} 

int main(){ 

    return 1; 
} 

我有一個編譯器警告,只需untitled: In function ‘bool probe()’:untitled:29: warning: control reaches end of non-void function - 但我也真的很感激任何信息或資源人們可以建議如何更好地編寫這種代碼...

回答

32

我會解決這個特定的功能:

bool probe() { 
#ifdef TARGET_OS_MAC 
    return probe_macosx(); 
#elif defined __linux__ 
    return probe_linux(); 
#elif defined _WIN32 || defined _WIN64 
    return probe_win(); 
#else 
#error "unknown platform" 
#endif 
} 

寫作這種方式,作爲一個鏈條,如果 - elif的,否則,消除錯誤,因爲這是不可能沒有一個有效的return語句或打編譯錯誤。

(我相信WIN32是爲32位和64位Windows定義,但我不能明確地告訴你不看它了。這將簡化代碼。)


不幸的是,你不能使用#ifdef _WIN32 || _WIN64:有關示例錯誤消息,請參閱http://codepad.org/3PArXCxo。如上所述,您可以使用定義爲運算符的特殊預處理


關於分裂平臺根據功能或整個文件(如suggested),你可能會或可能不希望這樣做。這取決於代碼的細節,例如平臺之間共享多少,以及您(或您的團隊)最適合保持功能同步等問題。此外,您應該在構建系統中處理平臺選擇,但這並不意味着您不能使用預處理器:爲每個平臺使用有條件定義的(通過makefile或構建系統)宏。實際上,這是模板和內聯函數通常最實用的解決方案,這使得它比試圖消除預處理器更加靈活。它與整個文件方法很好地結合在一起,所以你仍然在適當的地方使用它。

您可能需要一個單獨的配置標題,它將所有各種編譯器和平臺特定的宏轉換爲您控制的衆所周知和理解的宏。或者,您可以將-DBEAKS_PLAT_LINUX添加到您的編譯器命令行中(通過您的構建系統)以定義該宏(請記住爲宏名稱使用前綴)。

+5

你對WIN32的定義是正確的... – Goz 2010-09-02 12:57:59

5

看起來沒有TARGET_OS_MAC,__linux__,_WIN32_WIN64是在你編譯你的代碼的時候定義的。

所以它就像你的代碼是:

bool probe(){ 
} 

這就是爲什麼編譯器會達到一個非空函數的末尾。沒有return條款。


此外,對於更一般的問題,深化發展多平臺/木構建築軟件/庫的時候,這裏是我的準則:

避免特殊情況。嘗試編寫與操作系統無關的代碼。

當處理系統特定的東西時,嘗試將東西包裝到「不透明」類中。例如,如果您正在處理文件(Linux和Windows上的不同API),請嘗試創建一個File類,該類將嵌入所有邏輯並提供通用接口,無論操作系統如何。如果某個功能在某個操作系統上不可用,請處理:如果該功能對特定操作系統沒有意義,則根本無需執行任何操作。

總之:#ifdef越少越好。不管你的代碼是多麼便攜,在發佈之前在每個平臺上測試它。

祝你好運;)

+0

非常感謝......我給那些在IRC(羅傑)上幫助過我的人提供了「正確」的答案,但這是很好的建議,一如既往。 – 2010-09-02 13:38:53

+0

@Beaks:沒問題;)很高興你得到了你的問題的答案。 – ereOn 2010-09-02 14:20:17

1

該警告是因爲如果沒有定義的實際定義,那麼你在探測功能沒有return。該修復程序被置於默認return

45

而不是重複自己,再次寫同一個#ifdef ....行,你可能更好的是在頭文件中聲明probe()方法,並提供三個不同的源文件,一個爲每個平臺。這也有一個好處,如果你添加一個平臺,你不必修改所有現有的源,但只需添加新的文件。使用你的編譯系統選擇適當的源文件。

實施例結構:

include/probe.h 
src/arch/win32/probe.cpp 
src/arch/linux/probe.cpp 
src/arch/mac/probe.cpp 

該警告是因爲探頭()不返回值。換句話說,三個#ifdefs都不匹配。

+5

聽到,聽到! (1)這增加了你的代碼的清晰度,(2)減少了對僅僅熟悉一個平臺的人閱讀它的心理努力,(3)不依賴於不可移植的不可移植的編譯器/平臺特定的標誌。 – 2010-09-02 12:48:57

+4

這個。也不要依賴編譯器定義的平臺宏,讓你的構建系統定義你自己的。 – 2010-09-02 12:50:47

+1

我知道它有它的用途,但恕我直言,預處理器應該被刪除,這就是所有跨平臺編碼應該如何完成的。 – 2010-09-02 12:54:50