お世話になっております_(._.)_
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
- 記事: 158
- 登録日時: 14年前
- 連絡を取る:
Re: マルチプラットフォーム開発について知りたいです
原則として、C++はコンパイル後コードでの移植性は極めて低いと言わざるを得ません。なぜなら、C++の特性上各マシン固有のマシン語にコンパイルされるのが通常であり、かつ同一のCPUであってもOSごとにシステムコールなどのAPIが異なるため、環境ごとに全く異なる実行バイナリが生成されるのが常だからです。
しかも、各環境のネイティブAPIに直接アクセスしているような場合であれば、ソースレベルの移植性もぐっと低くなります。マルチプラットフォームを実現するためには、環境ごとに異なる部分をラッパーを挟んで共通化する必要があります。
つまり、mobaさんが考えているとおり、WindowsではDxライブラリ、MacではSFMLを使うというライブラリを用意して、#ifdefか何かで切り替えるようにすれば、ソースレベルでの移植性を確保することはできます(が、そもそもSFMLはクロスプラットフォームです)。ほかにも、GLibや、C++であればboostなどのクロスプラットフォームなライブラリを利用することができます。
注意しなければならないのは、C/C++の標準ライブラリを使用するときに、処理系定義の振る舞いや未定義のそれに依存するコードを書いてしまうと、移植性が損なわれてしまうということです。具体例としては、ファイルサイズを取得したい場合に、 というコードがよく書かれますが、Cの規格上バイナリモードのストリームに対するfseek(file,0,SEEK_END)は未定義の動作とされているので、移植性が損なわれてしまいます。この例では、boost::filesystemなどを利用することによって、移植性を保ちつつこれらの処理を書くことができます。
しかも、各環境のネイティブAPIに直接アクセスしているような場合であれば、ソースレベルの移植性もぐっと低くなります。マルチプラットフォームを実現するためには、環境ごとに異なる部分をラッパーを挟んで共通化する必要があります。
つまり、mobaさんが考えているとおり、WindowsではDxライブラリ、MacではSFMLを使うというライブラリを用意して、#ifdefか何かで切り替えるようにすれば、ソースレベルでの移植性を確保することはできます(が、そもそもSFMLはクロスプラットフォームです)。ほかにも、GLibや、C++であればboostなどのクロスプラットフォームなライブラリを利用することができます。
注意しなければならないのは、C/C++の標準ライブラリを使用するときに、処理系定義の振る舞いや未定義のそれに依存するコードを書いてしまうと、移植性が損なわれてしまうということです。具体例としては、ファイルサイズを取得したい場合に、 というコードがよく書かれますが、Cの規格上バイナリモードのストリームに対するfseek(file,0,SEEK_END)は未定義の動作とされているので、移植性が損なわれてしまいます。この例では、boost::filesystemなどを利用することによって、移植性を保ちつつこれらの処理を書くことができます。
Re: マルチプラットフォーム開発について知りたいです
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専用のソフトが多くあるようなので不思議です。
よろしくお願いいたします_(._.)_
> 原則として、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
- 記事: 158
- 登録日時: 14年前
- 連絡を取る:
Re: マルチプラットフォーム開発について知りたいです
算術演算や、分岐/繰り返しなどの制御などはCPU命令で処理するのが普通です(当然、CPUの種類ごとに命令コードは異なります)が、コンピューターのリソース(メモリ、ファイルなど)などはOSのシステムコールを通してアクセスします。moba さんが書きました: ・計算1つをとってみてもOS毎に過程に差がある (そういった部分はAPIとして書いてあってOSから提供される?)
・したがって生成されるコードは環境毎に異なるが、
同じ(見た目の)コードを様々な環境向けにそれぞれコンパイルすることはできる
という感じでしょうか。
ただし、算術演算や制御文などはC/C++の規格によってある程度定められていますから、1+1やwhile文の振る舞いについての移植性に悩むことはほとんどありません。一方、システムコールは環境ごとに大きく異なりますから、この部分は#ifなどで環境ごとに分ける必要があります。
fseekにはfseekでC/C++の規格が想定している使い方とそれに応じた挙動が規定されています。それを逸脱しない限りは規格によって定められたように振る舞います。逆にそれを逸脱すると、どのような事態になろうと規格の知ったことではありませんということになります。moba さんが書きました: 処理系未定義 で検索しました。
処理系や処理系未定義という概念、その一覧がヒットしました。
ありがとうございます! でもたぶん分かっていません!
fseekは、そのまま使うとどの環境向けにコンパイルされるのでしょうか。
それがコンパイラ毎に代わるのでしょうか。
boost::filesystemはfseekとはどう違うのでしょうか。
もしもfseekが使い物にならないならば、なぜfseekが置かれているのでしょうか。
追記:規格として動作が? 未定義ということでしたか。なぜそんなことにしているのでしょうか。
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専用なのでクロス開発にはほとんど役に立たないと考えたほうがいいでしょう。
Re: マルチプラットフォーム開発について知りたいです
お世話になります。
基本的にどの環境向けにもコンパイルできるように標準でコンパイラが対応している
ということですか。
それとも、同じ機械語のコードがどの環境でも動くということなのでしょうか。
前者かと思うのですが、「C++はどこでも動く」ような表現を聞いたのでひっかかっています。
後は報告です!
移植性はテキストエディタによってはチェックしてくれそうですね。
(実際にやっていることは他のことかもしれませんが…)
ちょっと今の僕では想像力が足らず、リスクをイメージできません。
いつか自分で試してみたいです。すぐに心が折れるかもしれませんが…
特にWinではOpenGLよりもDirectXの方が画像関係の動作が速いと聞いたので、
少しでもいいとこ取りできないかなと。
やめておいた方がよさそうなですね…
C/C++の規格によって定められているということは、ただし、算術演算や制御文などはC/C++の規格によってある程度定められていますから、1+1やwhile文の振る舞いについての移植性に悩むことはほとんどありません。一方、システムコールは環境ごとに大きく異なりますから、この部分は#ifなどで環境ごとに分ける必要があります。
基本的にどの環境向けにもコンパイルできるように標準でコンパイラが対応している
ということですか。
それとも、同じ機械語のコードがどの環境でも動くということなのでしょうか。
前者かと思うのですが、「C++はどこでも動く」ような表現を聞いたのでひっかかっています。
後は報告です!
ぼんやりと違いが分かりました。規格が振る舞いを保証しない場合には大別して「処理系定義の動作」「未定義の動作」があります
規格というのが今回のポイントみたいですね。コードの移植性を高めるためには、できる限りC/C++の規格に従ったコードを書き、未定義の動作に依存するコードは書かないことが重要です。
移植性はテキストエディタによってはチェックしてくれそうですね。
#ifで分岐する、といったことを内側でやってくれるんですね。boost::filesystemは外部ライブラリです。したがって規格に定められているわけではありませんが、boostは非常に移植性の高いライブラリなので、boostを利用している部分は様々な環境で動作させることができます。
(実際にやっていることは他のことかもしれませんが…)
クロスプラットフォーム目的でcocos2d等を使うのは、やはりリスクが大きいからなのですね。マルチプラットフォームはやはり難しいですよ。開発環境以外の環境での振る舞いもきちんと理解していなければなりませんし、コード量も当然増えますから、バグの混入の可能性も高くなりますし。
ちょっと今の僕では想像力が足らず、リスクをイメージできません。
いつか自分で試してみたいです。すぐに心が折れるかもしれませんが…
一度DxLibで組んでから、SFMLに差し替えられないかと考えていました。とはいうものの、DXライブラリはWindows Desktop専用なのでクロス開発にはほとんど役に立たないと考えたほうがいいでしょう。
特にWinではOpenGLよりもDirectXの方が画像関係の動作が速いと聞いたので、
少しでもいいとこ取りできないかなと。
やめておいた方がよさそうなですね…