web-dev-qa-db-ja.com

C ++アプリケーションはクロスプラットフォームですか?

私が学生として最初に学んだことの1つは、C++アプリケーションが異なるオペレーティングシステムで実行されないことです。最近、QtベースのC++アプリケーションがどこでも実行されることを読みました。それで、何が起こっているのでしょうか? C++アプリケーションはクロスプラットフォームですか?

47
Antony
  1. ソースコード互換。ソースコードをコンパイルすると、どこでも実行されます。

  2. API/ABIの互換性。 OSは、コードが理解できる方法でコンポーネントへのインターフェイスを提供しますか?

  3. バイナリ互換性。コードはターゲットホストで実行できますか?

ソースコード互換

C++は、構造、メモリ、ファイルの読み書き方法を定義する標準です。

#include <iostream>
int main( int argc, char ** argv )
{
     std::cout << "Hello World" << std::endl;
}

データを処理するために記述されたコード(例:grepawksed)はクロスプラットフォームです。

ユーザーと対話する場合、最新のオペレーティングシステムにはGUIがあり、これらはクロスプラットフォームではなく、特定のプラットフォーム用にコードが記述されます。

qtwxWidgetsなどのライブラリには複数のプラットフォームの実装があり、qtまたはWindowsの代わりにiOSをプログラムできます。結果は両方と互換性があります。

これらの匿名化ライブラリの問題は、プラットフォームXの特定の利点の一部を奪い、プラットフォーム間の均一性を確保することです。

この例は、Windowsを使用してWaitForMultipleObjects関数を使用すると、さまざまなタイプのイベントが発生するのを待つことができます。UNIXのfork関数は、重要な共有状態で実行されるプロセスのコピー。 UIでは、フォームの外観と動作はわずかに異なります(たとえば、カラーピッカー、最大化、最小化、ウィンドウの外でマウスを追跡する機能、ジェスチャーの動作)。

行う必要のある作業が重要な場合、特定のアプリケーションの利点を活用するために、プラットフォーム固有のコードを記述したくなる場合があります。

Cライブラリsqliteは広くクロスプラットフォームコードですが、その低レベルIOはプラットフォーム固有であるため、データベースの整合性を保証できます(データは実際にディスクに書き込まれます)。

そのため、Qtなどのライブラリは機能し、満足のいく結果が得られない場合があり、ネイティブコードを記述する必要があります。

API/ABIの互換性

UNIXとWindowsの異なるリリースには、何らかの互換性があります。これにより、OSの1つのバージョン用にビルドされたバイナリを、OSの他のバージョンで実行できます。

UNIXでは、ビルドマシンの選択により互換性が定義されます。サポートする最下位のOSリビジョンはビルドマシンである必要があり、重大な変更(ライブラリの廃止)が行われるまで、後続のマイナーバージョンと互換性のあるバイナリが生成されます。

WindowsおよびMac OS Xでは、SDKを選択します。これにより、一連のOSを対象として、重大な変更に関する同じ問題を解決できます。

Linuxでは、各カーネルリビジョンはABIと互換性がなく、カーネルリビジョンごとにカーネルモジュールを再コンパイルする必要があります。

バイナリ互換性

これは、CPUがコードを理解する能力です。これは、x64チップがx86コードを実行できる(OSのサポートに依存する)可能性があるため、思っているよりも複雑です。

通常、C++プログラムはコンテナ(PE実行可能ファイル、ELF形式)内にパッケージ化され、オペレーティングシステムはこれを使用してコードとデータのセクションをアンパックし、ライブラリをロードします。これにより、最終プログラムはバイナリ(コードのタイプ)とAPI(コンテナの形式)の両方の非互換性の形式になります。

また、今日x86 Windowsアプリケーション(Visual Studio 2015上のWindows 7を対象とする)をコンパイルする場合、プロセッサーにSSE2命令(約10年前のCPU)がないとコードの実行に失敗する可能性があります。

最後にApple PowerPCからx86に変更されたとき、古いPowerPCコードをx86プラットフォームのエミュレーターで実行できるエミュレーション層を提供しました。

したがって、一般的にバイナリの非互換性は不明瞭な領域です。無効な命令(SSE2など)を識別するOSを生成し、動作をエミュレートする障害で、これは新しい機能が登場するにつれて更新され、バイナリ互換性がなくてもコードを実行し続けることができます。

プラットフォームが命令セットの形式を実行できない場合でも、エミュレートして互換性のある動作をすることができます。

61
mksteve

標準C++は、「一度だけ書いてどこでもコンパイル」という意味ではクロスプラットフォームですが、「一度だけコンパイルしてどこでも実行」という意味ではありません。

つまり、標準C++でプログラムを作成すると、C++の標準に準拠した実装を備えた任意のターゲット環境でプログラムをコンパイルして実行できます。

ただし、プログラムをマシンでコンパイルし、バイナリを出荷して、他のターゲットで動作することを期待することはできません。 (少なくとも一般的ではありません。もちろん、特定の条件下でC++コードからバイナリを配布できますが、実際のターゲットに依存します。これは幅広い分野です。)


もちろん、gccの可変長配列やサードパーティライブラリのような追加の非標準機能を使用する場合、それらの拡張機能とライブラリを提供するシステムでのみコンパイルできます。

QtやBoostなどのいくつかのライブラリは多くのシステム(少なくともLinux、Mac、Windowsでは2つ)で利用できるため、これらを使用してもコードはクロスプラットフォームのままになります。

58
Baum mit Augen

さまざまなプラットフォーム上でソースをコンパイル can compiles すると、同じソースベースからさまざまなバイナリを取得できます。

これは、「一度コンパイルして、どこでも実行適切なVMを使用 JavaまたはC#で行う)ではなく、一度書き込み、コンパイルどこでも適切な環境で "Cが常に行っている方法。

標準ライブラリは必要なものをすべて提供するわけではないため、その機能を提供するにはサードパーティのライブラリを探す必要があります。 Boost、Qt、GTK +、wxWidgetsなどの特定のフレームワークは、それを提供できます。これらのフレームワークareは異なるプラットフォームでcompileのように記述されているため、前述の意味でクロスプラットフォーム機能を実現できます。


C++コードをクロスプラットフォームにしたい場合は、さまざまな注意事項があります。

明白なことは、データ型を仮定するソースです。ここでlongは32ビットで、64ビットである可能性があります。データ型の配置と構造体のパディングは異なる場合があります。 size_t/size_type/uint16_t typedefsなどの「安全にプレイする」方法と、wchar_tstd::wstringのような間違った方法があります。 「正しくする」には規律といくらかの経験が必要です。

すべてのコンパイラが同等に作成されるわけではありません。他のC++コンパイラでコンパイルするソースが必要な場合、すべての最新C++言語機能を使用したり、これらの機能に依存するライブラリを使用したりすることはできません。 互換性チャート を最初に確認してください。

もう1つは endianess です。ほんの一例として、あるプラットフォーム(x86またはx86_64など)のファイルに整数のストリームを書き込んでから、別のプラットフォーム(POWERなど)で再度読み取ると、問題が発生する可能性があります。なぜ整数をファイルに書き込むのですか?さて、UTF-16 is integers ...繰り返しますが、規律といくつかの経験はこれをやや痛みのないものにするために大いに役立ちます。

すべてのthoseボックスをチェックしたら、ライブラリのの可用性を確認する必要がありますコードのベースにします。 std::は安全ですが(上記の「すべてのコンパイラが同等に作成されるわけではありません」を参照)、boost::ほど無害なものは、メインストリームを超えて見ていると問題になる可能性があります。 (私は、過去数年間にAIX/Visual Ageに関する1つまたは2つのショートッパーを修正するためにブーストの人たちを助けましたが、それは単に彼らが新しいリリースをテストするためのプラットフォームにアクセスできなかったからです...)

ああ、さまざまなライセンススキームに注意してください。 QtやCygwinなどのクロスプラットフォーム機能を改善するフレームワークには、文字列が添付されています。それは、適切な状況では彼らが大きな助けではないということではなく、コピーレフト/独自のライセンス要件を知っておく必要があるというだけです。


つまり、実行可能なファイルを作成する Wine ( "Wine is not emulation")がありますコンパイル済み Windows向けrunさまざまなUnix -類似システム(Linux、OS X、* BSD、Solaris)。その機能には一定の制限がありますが、常に改善されています。

18
DevSolar

はい。いいえ。クロスプラットフォームC++コードとは何ですか?クロスプラットフォームC++コードは、変更することなく異なるオペレーティングシステムでコンパイルできるコードです。

つまり、プラットフォームに依存するヘッダーを明示的に使用すると、コードはクロスプラットフォームではなくなります。 Qtはこの問題を次の方法で解決します。プラットフォーム固有のすべてのラッパーを提供します。たとえば、QFileを使用してファイルを開いたり、読み書きしたりするとします。あなたのコードは次のようになります

QFile file(filename);
file.open(QFile::ReadOnly);
//other stuff

そのOSに適したコンパイラとQtライブラリがある限り、どのOSでもこのコードをコンパイルできます。 QFileの下に隠されたコードはOSに適したファイル処理関数を使用しますが、それは心配する必要はありません。

また、標準ライブラリのみを使用する場合は、C++コンパイラが存在する任意の場所でコードをコンパイルできます。

ただし、すでにコンパイルされているアプリケーションは、Javaアプリケーションがそうであるように、クロスプラットフォームではありません-たとえば、Windows用にアプリケーションをコンパイルしてから実行することはできませんLinuxでは、代わりにLinuxでコードを再コンパイルする必要があります。

6
SingerOfTheFall

C++はプログラミング言語です。テキスト。そのため、どこでも実行されません。

準拠する標準C++コードは、すべてのプラットフォームで同等に動作であることが期待されています。必要に応じて「クロスプラットフォーム」。 (厳密に)準拠するC++コードを作成するには、実際の実装の最終的な詳細に依存することが多く、これはC++自体が目標とするターゲットから継承されるため、細心の注意が必要です。

C++プログラムではなく、まだC++コードについて話していることに注意してください。確かに、「プログラム」という用語を使用する場合、C++についてはもう話していないため、これ以上の保証はありません。むしろ、コンパイラの出力。実行可能形式、ISA、ABI、低レベルルーチンなど、移植性が次第に衰退し始めています。
それに頼ることができますか?できない場合は、C++プログラムを再コンパイルするか、プラットフォーム固有の要素を使用して、実行環境に統合する必要があります。

4
edmz

C++はクロスプラットフォームです。これを使用して、多くの異なるオペレーティングシステムで実行されるアプリケーションを構築できます。

クロスプラットフォームではないものは、C++をオブジェクトコードに変換するコンパイラです。私の知る限り、必要な機能をすべて備えた単一のコンパイラはありません。そのため、C++プログラムをコンパイルするときに、Windows、Linux、Mac OSで自動的に実行されます。

Qt Creatorは複数のコンパイラーと統合されており、ビルドを自動化します。異なるセットアップとターゲットプラットフォームを簡単に切り替えることができます。デスクトップ環境だけでなく、モバイルデバイス用のC++アプリケーションの構築、実行、展開のサポートを提供します。

3
dspfnder