クロスプラットフォームの互換性(C ++)を確保するためのテクニック?


13

(フレームワークによれば)クロスプラットフォームであると想定されている、初期のC ++プロジェクトの1つを終えていました。ライブラリはすべてクロスプラットフォームであるため、OSXビルドを「後で」実行するのは簡単だと思い、プロジェクトをWindowsとVisual Studioで完全に開発しました。これは事実ではないことが判明しましたが、「Windowsコード」が正しく実行されず、修正すべきコンパイルエラーがいくつかありました。

コードがすべてのプラットフォームと互換性があることを事前に保証するために、どのような手法が存在しますか?すべてのプラットフォームを同時に開発し、新しいプラットフォームバージョンを次々に開発するのではなく、新しい機能が追加されたときに、すべてのプラットフォームに対して同時にコードをテストしますか?(*)

ツールに依存するのではなく、使用するツールに関係なく、クロスプラットフォームの互換性を支援する「開発プロセス」ではなく、具体的にアドバイスを探します。上記の(*)のように。


具体的には、WDL-OL(https://github.com/olilarkin/wdl-ol)といくつかのクロスプラットフォームDSPライブラリを使用してVSTプラグインを開発しています。WDL-OLプロジェクトにはVSプロジェクトとXcodeプロジェクトの両方がセットアップされていますが、問題はライブラリーに起因し、コンパイラーの違いに起因すると推測します。


1
する方法はありません確実に可搬性が向上する唯一の方法、/最大化ポータビリティ
phuclv

そして、なぜこれは重複していないのですか?私は同様の質問がたくさんあったと信じて
phuclvは

アプリケーションは何をしていますか?どのように使用しますか?コマンドラインで、またはいくつかのグラフィカルインターフェースを介して?質問編集して改善してください。
バジルスタリンケビッチ

また、どのフレームワークを使用していますか?
バジルスターリンケビッチ

回答:


15

移植可能なコードの作成は非常に難しい場合があります。

まず、言語に関連するいくつかの明らかなアドバイス:

  • 標準のC ++を使用し、未定義の動作を慎重に避けてください
  • 主に標準ライブラリ(およびboostなどのポータブルライブラリ)に依存
  • 予想されるすべてのヘッダーを常に含めます。ヘッダーは別のヘッダー(つまり、特定の実装)に含まれているため、ヘッダーは必要ないと想定しないでください。これにより、コンパイルエラーが発生する可能性があります。
  • コンパイラでサポートされているが、C ++標準では保証されていない構造匿名の構造体可変長配列など)は避けてください。コンパイルエラーが発生する可能性があります。
  • コンパイラー・オプションを使用して、コンプライアンスの実施を支援します(コンパイラー固有の拡張機能を無効にし、返される警告メッセージのレベルを最大化します)
  • コードが機能するだけでは不十分であることに注意してください:実装に依存する移植性の落とし穴が多くあります:(基本的な)データ型のサイズ、デフォルト署名または署名されない文字、エンディアン性に関する仮定、式の評価の順序副作用などを使用する

次に、いくつかの設計上の推奨事項:

  • 同等のオペレーティングシステム機能に代わる標準ライブラリを優先する
  • オペレーティングシステムの依存関係の使用を可能な限り分離します(たとえば、条件付きコンパイルで制御されるラッパー関数で)

最後に、繊細な点:

  • 文字エンコード:多くのシステムでutf8に依存できます。しかし、Windowsの場合、システムがansiまたはutf-16を期待するため、より繊細です。あなたはもちろん、(同様のtypedefに頼ることができるTCHAR)が、これはその後、(例えば、標準ライブラリと組み合わせて挑戦することができますcoutwcout使用されるように応じて、使用している場合charwchar_t
  • GUI /グラフィックス/高度なI / Oの場合、期待/要件に合ったポータブルライブラリが見つからない場合は、OS固有のコンポーネントを分離するためにアーキテクチャ全体を設計します。ここでは、さまざまな相互作用や概念が関係しているため、ラッパーでは不十分な場合があります。
  • たとえば、抽象ファクトリー(OS固有のUIなどの関連オブジェクトのファミリーを設計するのに理想的)またはメディエーター(関連オブジェクトのファミリー間のコラボレーションを実装するのに理想的)などの興味深いデザインパターンを活用して、条件付きコンパイルと併用します。

しかし、これらは単なるアドバイスです。この分野では、確実性を得ることができません。


-Wall -Wextra -Werror
パイプ

1
@pipeまた、する必要があります-pedantic
5gon12eder

@ 5gon12ederこの回答の文脈で非常に良い点。
パイプ

11

コードをビルド、実行、テストする以外のプラットフォームとの互換性を保証できるものはありません。したがって、すべての正気な人々のアプローチは、プロジェクトをビルド、実行、およびテストする必要のあるすべてのプラットフォームでアプリケーションをビルド、実行、およびテストすることです。

継続的インテグレーション(CI)は、一部のプラットフォーム(主にLinux)向けの安価なまたは無料のビルドエージェントを入手し、Windowsで開発を行い、問題が発生した場合にLinuxに戻ることができるため、小規模プロジェクトの負担をかなり軽減できます。

ただし、OSX CIはかなり注意が必要です。


CIとは何ですか?
mavavilj

5
継続的インテグレーション-基本的にビルドとテストを実行する多数のサーバー。
-DeadMG

@DeadMGあなたはMozilla Tinderboxのような意味ですか?
ダミアンジェリック

1
トラヴィスCIは、無料のOSXのビルドホストを提供
Daenyth

Cmakeを使用してください。
raaj

9

「開発プロセス」を求めていて、主な開発プラットフォームがVisual Studioを搭載したWindowsである場合、「windows.h」を含めずにプロジェクトをビルドすることをお勧めします。コードをリファクタリングする必要がある多くの場所を示す多くのコンパイルエラーが発生します。たとえば、「DWORD」は#definedにならず、uint32_tすべての場所で置き換える必要があります(グーグルでstdint.h検索すると、整数型とそのクロスプラットフォーム定義に関する有用な情報が見つかります)。次に、次のようなWin32 APIへのすべての呼び出しを置き換える必要があります。Sleep()クロスプラットフォームに相当するものを使用します(繰り返しますが、googleはstack * .comサイトに関連する質問と回答を表示する親友です)。あなたはおそらくあなたのコードに関連するすべてのクロスプラットフォーム置換を見つけることに成功しないでしょう、そしてあなたはあなたのinclude "windows."ディレクティブを返さなければなりませんが、それを下に置く必要があります#ifdef _WIN32-詳細はこちら

より具体的な質問をし続け、答えを得る-これは「開発プロセスはどうあるべきか」に対する一般的な提案です。

編集1 もう1つの私の提案は、Windows開発マシンでgccおよび/またはclangを使用することです(Visual Studioとともに)


3

それはあなたが言及する「いくつかのコンパイルエラー」に依存します。それらが何であるかを知らなければ、具体的にすることは不可能です。

Windows / Linux / iOS / Android / Mac用のクロスプラットフォームコードがあります。それぞれの新しいプラットフォームは、最初に追加されたときにいくつかの余分なエラーと警告をもたらしました。どのコンストラクトが問題を引き起こすかをすぐに知ることができます。それらを避けるか、#ifdefsでヘッダーに違いを抽象化します。#ifdefコード自体内のプラットフォーム間では絶対にしないでください。

一例:

void myfunction(MyClass &);
myfunction(MyClass());

が戻ったMyClassmyfunctionに削除される一時インスタンスを作成します。私のC ++コンパイラのいくつかでは、そのインスタンスは読み取り/書き込み可能です(そして、一時的であり、すぐに破棄されるという事実はコンパイラを心配しません)。他のものと一緒に、myfunction再定義する必要がありますconst MyClass &、またはコンパイラは文句を言います。C ++標準が何を言っているか、どのコンパイラが正しいか、どのコンパイラが間違っているかは関係ありません。エラーに何度か遭遇した後、(a)型の一時変数を宣言してMyClass渡すmyfunctionか、(b)参照constを宣言し、あちこちで解体myfunctionするために使用しmutableます。

結論:経験を蓄積し、独自のコーディング標準を開発します。


2
これは、MSVCの機能の誤りです。あなたのポイントが、1つのシステムで開発することで、これらが忍び寄ることを可能にするなら、ポイントがとられます。しかし、その特定のことはあなたがやるべきことではありません。
JDługosz

1
複数のツールチェーンを使用する利点の1つは、それらが受け入れる共通のサブセットは、それぞれが個別に受け入れるものよりも、標準に準拠した正しいC ++である可能性が高いことです。あなたの場合、示されているコードは標準によって明らかに間違っており、言及された修正は両方とも有効な代替案です。標準何を言っているは問題はないと思います。
5gon12eder

1
または、クロスプラットフォームのC ++は、標準が言うものよりも制限的だと思います。言い換えれば、たとえ標準でそう言われていても、サポートしなければならないプラットフォームの最小公分母(またはベンダー機能の最小値)の影響を受けます。C ++ 11を除外しなければならないオープンソースライブラリがたくさんあります。これは、その構成要素の一部(市民など)がC ++ 11に対応していないためです。
rwong

3

移植性を支援する可能な方法は、C ++ 11標準で提供される宣言と機能のみに依存し、POCOQtなどのクロスプラットフォームライブラリとフレームワークを使用することです。

しかし、これでもフェイルプルーフではありません。格言を覚えている

移植可能なプログラムなどはありません。正常に(特定のプラットフォームに)移植されたプログラムのみがあります。

練習、規律、および多くの経験があれば、通常、プログラムを別のプラットフォームに移植すること迅速に行えます。しかし、経験とノウハウは非常に重要です。


1
別のアドバイスは、異なる人やチームによって移植が行われた場合、コードの変更をメインラインに再統合する必要があるということです。それ以外の場合、プラットフォームの違いは、それを行ったチームによって蓄積された知識になります。
rwong
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.