web-dev-qa-db-ja.com

クロスプラットフォームC ++コードの作成(Windows、Linux、およびMac OSX)

これは、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-しかし、この種のコードをより良く書く方法について人々が提案できる情報やリソースも本当にありがたいです。

35
Lee Hambley

この特定の機能に対処します。

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を追加して、そのマクロを定義することもできます(マクロ名にプレフィックスを使用することを忘れないでください)。

32
Roger Pate

同じ#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のいずれも一致しません。

46
stijn

TARGET_OS_MAC__linux___WIN32または_WIN64は、コードをコンパイルするときに定義されます。

あなたのコードは次のようになりました:

bool probe(){
}

それが、コンパイラが非void関数の最後に到達することについて文句を言う理由です。 return句はありません。


また、より一般的な質問については、マルチプラットフォーム/アーキテクチャソフトウェア/ライブラリを開発する際のガイドラインを以下に示します。

特定のケースを避けてください。 OSに依存しないコードを記述してください。

システム固有のものを扱うときは、「不透明な」クラスに物事をラップしてみてください。例として、ファイル(LinuxとWindowsで異なるAPI)を扱っている場合は、オペレーティングシステムに関係なく、すべてのロジックを埋め込み、共通のインターフェイスを提供するFileクラスを作成してみてください。いずれかのOSで使用できない機能がある場合は、それを処理します。特定のOSで機能が意味をなさない場合は、何もしないでよいことがよくあります。

要するに:#ifdef よりいい。また、コードの移植性に関係なく、リリースする前にすべてのプラットフォームでテストしてください。

幸運を ;)

5
ereOn

これに何か追加するために、上記の傑出したオプション以外に、__linux___WIN32ディレクティブがコンパイラに認識されていますが、TARGET_OS_MACディレクティブはそうではありませんでした。 __Apple__。ソース: http://www.winehq.org/pipermail/wine-patches/2003-July/006906.html

1
Lee Hambley

警告は、定義が実際に定義されていない場合、プローブ関数にreturnがないためです。その修正は、デフォルトのreturnに入れられます。

1
Tristan