これは、C++で少し複雑なものでも書く最初の試みです。Objective-Cおよび.NETアプリからインターフェイスできる共有ライブラリを構築しようとしています(その部分は後で説明します...)
私が持っているコードは-
_#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
-しかし、この種のコードをより良く書く方法について人々が提案できる情報やリソースも本当にありがたいです。
この特定の機能に対処します。
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
}
If-Elif-elseのチェーンとしてこのように記述すると、有効なreturnステートメントがないか、#errorがヒットしないとコンパイルできないため、エラーがなくなります。
(WIN32は32ビットと64ビットの両方のWindowsで定義されていると思いますが、調べずに明確に説明することはできませんでした。それによりコードが簡素化されます。)
残念ながら、#ifdef _WIN32は使用できません|| _WIN64:サンプルエラーメッセージについては、 http://codepad.org/3PArXCxo を参照してください。上記のように、特別な前処理専用defined演算子を使用できます。
プラットフォームを機能またはファイル全体( 推奨 として)に応じて分割することに関して、あなたはそれをしたいかもしれません。プラットフォーム間で共有される量や、機能の同期を維持するために最適なもの(他の問題など)など、コードの詳細に依存します。
さらに、ビルドシステムでプラットフォームの選択を処理する必要がありますが、これはプリプロセッサを使用できないことを意味しません。各プラットフォームに対して(メイクファイルまたはビルドシステムによって)条件付きで定義されたマクロを使用します。実際、これは多くの場合、テンプレートとインライン関数を使用した最も実用的なソリューションであり、プリプロセッサを排除するよりも柔軟になります。ファイル全体のアプローチとうまく組み合わされているため、必要に応じてそれを使用します。
さまざまなコンパイラ固有およびプラットフォーム固有のすべてのマクロを、ユーザーが制御する既知の理解されたマクロに変換する単一の構成ヘッダーが必要な場合があります。または、ビルドシステムを通じてコンパイラコマンドラインに-DBEAKS_PLAT_LINUXを追加して、そのマクロを定義することもできます(マクロ名にプレフィックスを使用することを忘れないでください)。
同じ#ifdef ....行を何度も何度も書く代わりに、ヘッダーでprobe()メソッドを宣言し、各プラットフォームに1つずつ、3つの異なるソースファイルを提供する方がよいでしょう。これには、プラットフォームを追加する場合、既存のソースをすべて変更する必要はなく、新しいファイルを追加するだけでよいという利点もあります。ビルドシステムを使用して、適切なソースファイルを選択します。
構造例:
include/probe.h
src/Arch/win32/probe.cpp
src/Arch/linux/probe.cpp
src/Arch/mac/probe.cpp
警告は、probe()が値を返さないためです。つまり、3つの#ifdefsのいずれも一致しません。
TARGET_OS_MAC
、__linux__
、_WIN32
または_WIN64
は、コードをコンパイルするときに定義されます。
あなたのコードは次のようになりました:
bool probe(){
}
それが、コンパイラが非void関数の最後に到達することについて文句を言う理由です。 return
句はありません。
また、より一般的な質問については、マルチプラットフォーム/アーキテクチャソフトウェア/ライブラリを開発する際のガイドラインを以下に示します。
特定のケースを避けてください。 OSに依存しないコードを記述してください。
システム固有のものを扱うときは、「不透明な」クラスに物事をラップしてみてください。例として、ファイル(LinuxとWindowsで異なるAPI)を扱っている場合は、オペレーティングシステムに関係なく、すべてのロジックを埋め込み、共通のインターフェイスを提供するFile
クラスを作成してみてください。いずれかのOSで使用できない機能がある場合は、それを処理します。特定のOSで機能が意味をなさない場合は、何もしないでよいことがよくあります。
要するに:#ifdef
よりいい。また、コードの移植性に関係なく、リリースする前にすべてのプラットフォームでテストしてください。
幸運を ;)
これに何か追加するために、上記の傑出したオプション以外に、__linux__
と_WIN32
ディレクティブがコンパイラに認識されていますが、TARGET_OS_MAC
ディレクティブはそうではありませんでした。 __Apple__
。ソース: http://www.winehq.org/pipermail/wine-patches/2003-July/006906.html
警告は、定義が実際に定義されていない場合、プローブ関数にreturn
がないためです。その修正は、デフォルトのreturn
に入れられます。