マルチプラットフォーム開発について知りたいです

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
moba
記事: 82
登録日時: 4年前

マルチプラットフォーム開発について知りたいです

#1

投稿記事 by moba » 4年前

お世話になっております_(._.)_
C++/DxLibでゲームを作りたい入門者です。何も分かっていません。
マルチプラットフォーム開発の方法や、あとから他のOSに対応するための方法を知りたいです。
適切な検索ができず、知りたいことを知れませんでした。
知識を得る手段をお伺いしたいです。以下のようなことを知るには、何をあたればいいでしょうか。
よろしくお願いします。

1.依存とは

C++はOS(やハード)に依存しないと聞いたのですが、なぜなのでしょうか。
どのような部分がOSに依存しますか。
なぜOSに依存する部分ができてしまうのですか。
OSに依存する部分は、OSが提供するインターフェース? が吸収? してしまえないものでしょうか。
依存する部分だけ差し替えればどの環境でも動くようにはなりませんか。

2.マルチプラットフォーム開発のリスクとは

ライブラリだけコンパイル時に差し替えるように書いておけば、
同じ(見た目で動く)ゲームがWinでもMacでもゲーム機でも簡単に動くのではないかと思いました。
e.g. DxLibをSFMLに差し替える
マルチプラットフォーム開発のリスクはどこにあるのでしょうか。
また、cocos2dやUnityがマルチプラットフォーム開発の点でもてはやされる(ように僕には見える)のはなぜですか。
むしろ、サポートが停止すれば新しいOSに対応できなくなって危険ではないでしょうか(Unity)。

追記
e.g. DxLibをSFMLに差し替える の部分ですが、
コードの中で使うライブラリ(ラッパー?)をMyLibとして、
MyLibがコンパイル時の設定でDxLibとSFMLに差し替わるようにすればいいのかなぁと
思っています。

アバター
tk-xleader
記事: 153
登録日時: 9年前
連絡を取る:

Re: マルチプラットフォーム開発について知りたいです

#2

投稿記事 by tk-xleader » 4年前

 原則として、C++はコンパイル後コードでの移植性は極めて低いと言わざるを得ません。なぜなら、C++の特性上各マシン固有のマシン語にコンパイルされるのが通常であり、かつ同一のCPUであってもOSごとにシステムコールなどのAPIが異なるため、環境ごとに全く異なる実行バイナリが生成されるのが常だからです。

 しかも、各環境のネイティブAPIに直接アクセスしているような場合であれば、ソースレベルの移植性もぐっと低くなります。マルチプラットフォームを実現するためには、環境ごとに異なる部分をラッパーを挟んで共通化する必要があります。
つまり、mobaさんが考えているとおり、WindowsではDxライブラリ、MacではSFMLを使うというライブラリを用意して、#ifdefか何かで切り替えるようにすれば、ソースレベルでの移植性を確保することはできます(が、そもそもSFMLはクロスプラットフォームです)。ほかにも、GLibや、C++であればboostなどのクロスプラットフォームなライブラリを利用することができます。

 注意しなければならないのは、C/C++の標準ライブラリを使用するときに、処理系定義の振る舞いや未定義のそれに依存するコードを書いてしまうと、移植性が損なわれてしまうということです。具体例としては、ファイルサイズを取得したい場合に、

コード:

// エラー処理は省略。
unsigned fileSize(const char* filename){
	using namespace std;
	FILE *file = fopen(filename,"rb");
	fseek(file,0,SEEK_END);
	unsigned size = ftell(file);
	fclose(file);
	return size;
}
というコードがよく書かれますが、Cの規格上バイナリモードのストリームに対するfseek(file,0,SEEK_END)は未定義の動作とされているので、移植性が損なわれてしまいます。この例では、boost::filesystemなどを利用することによって、移植性を保ちつつこれらの処理を書くことができます。

moba
記事: 82
登録日時: 4年前

Re: マルチプラットフォーム開発について知りたいです

#3

投稿記事 by moba » 4年前

tk-xleaderさんご回答ありがとうございます!

> 原則として、C++はコンパイル後コードでの移植性は極めて低いと言わざるを得ません。

C++のコードは、環境毎に別々の機械語にコンパイルされることを
理解できていませんでした!

・計算1つをとってみてもOS毎に過程に差がある (そういった部分はAPIとして書いてあってOSから提供される?)
・したがって生成されるコードは環境毎に異なるが、
 同じ(見た目の)コードを様々な環境向けにそれぞれコンパイルすることはできる

という感じでしょうか。

> コンパイル後に移植性が低くなる
> マルチプラットフォームを実現するためには、環境ごとに異なる部分をラッパーを挟んで共通化する必要がある

予想が大体あっていたようで胸熱です。ふふふ。
でもこうしたことが検索してもヒットしません。
どう検索するべきだったのでしょうか。

> 注意しなければならないのは、C/C++の標準ライブラリを使用するときに、
> 処理系定義の振る舞いや未定義のそれに依存するコードを書いてしまうと、移植性が損なわれてしまうということです。

処理系未定義 で検索しました。
処理系や処理系未定義という概念、その一覧がヒットしました。
ありがとうございます! でもたぶん分かっていません!

fseekは、そのまま使うとどの環境向けにコンパイルされるのでしょうか。
それがコンパイラ毎に代わるのでしょうか。
boost::filesystemはfseekとはどう違うのでしょうか。
もしもfseekが使い物にならないならば、なぜfseekが置かれているのでしょうか。

「処理系未定義」の対になる概念はないものでしょうか。
No.1で触れた「C++はどこでも動く」というような文章は、
処理系未定義の動作ではない部分を指していたのではないかと思います。
処理系未定義ではない動作は存在し得るのでしょうか。
もしもint a = 5; が処理系だけれど未定義ではないとすれば、
なぜ未定義でなくて済んでいるのでしょうか。未定義とは何ですか。

追記:規格として動作が? 未定義ということでしたか。なぜそんなことにしているのでしょうか。

No.1の残りの質問
Q:マルチプラットドーム開発は難しい?
動作速度さえ考慮しなければ、
ラッパーを挟めば簡単に実現できるものではないのでしょうか。
Win/Mac/Linux/android専用のソフトが多くあるようなので不思議です。


よろしくお願いいたします_(._.)_

アバター
tk-xleader
記事: 153
登録日時: 9年前
連絡を取る:

Re: マルチプラットフォーム開発について知りたいです

#4

投稿記事 by tk-xleader » 4年前

moba さんが書きました: ・計算1つをとってみてもOS毎に過程に差がある (そういった部分はAPIとして書いてあってOSから提供される?)
・したがって生成されるコードは環境毎に異なるが、
 同じ(見た目の)コードを様々な環境向けにそれぞれコンパイルすることはできる

という感じでしょうか。
 算術演算や、分岐/繰り返しなどの制御などはCPU命令で処理するのが普通です(当然、CPUの種類ごとに命令コードは異なります)が、コンピューターのリソース(メモリ、ファイルなど)などはOSのシステムコールを通してアクセスします。
 ただし、算術演算や制御文などはC/C++の規格によってある程度定められていますから、1+1やwhile文の振る舞いについての移植性に悩むことはほとんどありません。一方、システムコールは環境ごとに大きく異なりますから、この部分は#ifなどで環境ごとに分ける必要があります。
moba さんが書きました: 処理系未定義 で検索しました。
処理系や処理系未定義という概念、その一覧がヒットしました。
ありがとうございます! でもたぶん分かっていません!

fseekは、そのまま使うとどの環境向けにコンパイルされるのでしょうか。
それがコンパイラ毎に代わるのでしょうか。
boost::filesystemはfseekとはどう違うのでしょうか。
もしもfseekが使い物にならないならば、なぜfseekが置かれているのでしょうか。

追記:規格として動作が? 未定義ということでしたか。なぜそんなことにしているのでしょうか。
 fseekにはfseekでC/C++の規格が想定している使い方とそれに応じた挙動が規定されています。それを逸脱しない限りは規格によって定められたように振る舞います。逆にそれを逸脱すると、どのような事態になろうと規格の知ったことではありませんということになります。
 C/C++のコードを移植するうえで最も気を付けなければならないのは、規格が保証する範囲というのはわりと狭いという事実です。規格が振る舞いを保証しない場合には大別して「処理系定義の動作」「未定義の動作」があります。前者はC/C++のコードとして正当であり、正常な動作をしますが、「どのような振る舞いをするか」というのは処理系が選択することができるものです。例えば、int型などの組み込み型のサイズや、構造体のパディング配置などです。後者はプログラムとして正常な動作をするかどうかさえ保証しません。典型例がNULLが代入されたポインタ変数を単項*演算子によってデリファレンスした場合です。
 したがって、コードの移植性を高めるためには、できる限りC/C++の規格に従ったコードを書き、未定義の動作に依存するコードは書かないことが重要です。処理系定義の動作を含むコードについては、#if命令を使うなどして処理系ごとにコードを分岐するか、あるいは修正することになります。

 boost::filesystemは外部ライブラリです。したがって規格に定められているわけではありませんが、boostは非常に移植性の高いライブラリなので、boostを利用している部分は様々な環境で動作させることができます。
moba さんが書きました: No.1の残りの質問
Q:マルチプラットドーム開発は難しい?
動作速度さえ考慮しなければ、
ラッパーを挟めば簡単に実現できるものではないのでしょうか。
Win/Mac/Linux/android専用のソフトが多くあるようなので不思議です。
 マルチプラットフォームはやはり難しいですよ。開発環境以外の環境での振る舞いもきちんと理解していなければなりませんし、コード量も当然増えますから、バグの混入の可能性も高くなりますし。
 ただ、クロスプラットフォームなライブラリを用意して、それ以外に依存しないように注意深くコードを書けば、ある程度移植性の高いコードになると思います。OSへのアクセスをすべてクロスプラットフォームのライブラリを通して呼び出していれば、ソースレベルでの移植性は大丈夫です。とはいうものの、DXライブラリはWindows Desktop専用なのでクロス開発にはほとんど役に立たないと考えたほうがいいでしょう。

moba
記事: 82
登録日時: 4年前

Re: マルチプラットフォーム開発について知りたいです

#5

投稿記事 by moba » 4年前

お世話になります。
ただし、算術演算や制御文などはC/C++の規格によってある程度定められていますから、1+1やwhile文の振る舞いについての移植性に悩むことはほとんどありません。一方、システムコールは環境ごとに大きく異なりますから、この部分は#ifなどで環境ごとに分ける必要があります。
C/C++の規格によって定められているということは、
基本的にどの環境向けにもコンパイルできるように標準でコンパイラが対応している
ということですか。
それとも、同じ機械語のコードがどの環境でも動くということなのでしょうか。
前者かと思うのですが、「C++はどこでも動く」ような表現を聞いたのでひっかかっています。

後は報告です!
規格が振る舞いを保証しない場合には大別して「処理系定義の動作」「未定義の動作」があります
ぼんやりと違いが分かりました。
コードの移植性を高めるためには、できる限りC/C++の規格に従ったコードを書き、未定義の動作に依存するコードは書かないことが重要です。
規格というのが今回のポイントみたいですね。
移植性はテキストエディタによってはチェックしてくれそうですね。
boost::filesystemは外部ライブラリです。したがって規格に定められているわけではありませんが、boostは非常に移植性の高いライブラリなので、boostを利用している部分は様々な環境で動作させることができます。
#ifで分岐する、といったことを内側でやってくれるんですね。
(実際にやっていることは他のことかもしれませんが…)
マルチプラットフォームはやはり難しいですよ。開発環境以外の環境での振る舞いもきちんと理解していなければなりませんし、コード量も当然増えますから、バグの混入の可能性も高くなりますし。
クロスプラットフォーム目的でcocos2d等を使うのは、やはりリスクが大きいからなのですね。
ちょっと今の僕では想像力が足らず、リスクをイメージできません。
いつか自分で試してみたいです。すぐに心が折れるかもしれませんが…
とはいうものの、DXライブラリはWindows Desktop専用なのでクロス開発にはほとんど役に立たないと考えたほうがいいでしょう。
一度DxLibで組んでから、SFMLに差し替えられないかと考えていました。
特にWinではOpenGLよりもDirectXの方が画像関係の動作が速いと聞いたので、
少しでもいいとこ取りできないかなと。
やめておいた方がよさそうなですね…

閉鎖

“C言語何でも質問掲示板” へ戻る