5

この質問が以前に尋ねられたことは知っていますが、マイナスを与えて繰り返しの質問を報告する前に、これについてしばらく考えてください。

以前のすべての回答で、オブジェクトのメモリ レイアウトはコンパイラに依存すると誰もが言いました。では、共有ライブラリ (*.dll、*.so) が c++ クラスをエクスポートおよびインポートでき、異なるコンパイラからのものであってもそれらを確実に組み合わせることができるのはなぜでしょうか? mingw で書かれた DirectX アプリケーションを考えてみましょう。DirectX は MSVC++ を使用してコンパイルされたので、それらの環境はどのようにメモリ レイアウトに同意するのでしょうか? DirectX が C++ クラスとポリモーフィズムに大きく依存していることは知っています。

別の質問: 選択したアーキテクチャ (Windows、Intel x86 など) があり、新しいコンパイラを作成しようとしているとしましょう。別のコンパイラによってコンパイルされた .dll lib によって提供されるクラス インスタンス (vtable、メンバー フィールド) にアクセスする方法を知るにはどうすればよいですか? それとも単にそのようなものですか: M$ は VC++ を記述しましたが、それ以来、それは書かれていない標準であり、他のすべてのコンパイラは「互換性の理由から」同じことを行いますか? Linux やその他の OS についてはどうでしょうか。

編集:

わかりました、DirectX の例は COM の仕様のために悪いものでした...

別の例: QT。私は mingw で QT を使用していますが、MSVC バージョンも利用できることを知っています。違いがヘッダーのみなのか、共有ライブラリ (dll-s) も異なるのかはわかりません。もしそうなら、qt ライブラリを含めてアプリを配布しなければならないということですか? (それなら、メモリとコードを共有するのはいいことですよね?)。それとも、それらは同じであり、とにかくそれについて不文律があるのでしょうか?

EDIT2:

共有されているものと共有されていないものを確認するためだけに、別のqtバージョン(msvc 2010)をインストールしました。共有されている (実際に共有されている) ライブラリは異なるようです。その場合、本当にqt-libsをアプリに提供する必要があるようです...そして、これは小さなことではありません(例:QtGui 8-9MB)。作成者が他のコンパイラ用のバージョンを提供するのにそれほど親切ではなかった、他の小さなライブラリはどうですか? 元のコンパイラに固執しているということですか? 異なるコンパイラでコンパイルされた 2 つの異なるライブラリを使用したい場合はどうすればよいですか?

4

2 に答える 2

9

基本的に、ABI について質問しています。

場合によっては (Itanium など)、ABI を指定するドキュメントがあり、基本的に誰もがそのドキュメントに従います。

DirectX の場合も少し同じです。Microsoft は COM の仕様を公開しているため、これらの仕様に従う人は誰でも、基本的にすべての COM オブジェクトと相互運用できます (当然のことですが、64 ビット コンパイラはおそらく機能しません)。 Windows 3.1 用に記述された 16 ビット COM オブジェクトを使用)。

他のほとんどのことについては、多かれ少なかれ自分で解決する必要があります。ドキュメントの形で少なくとも少し公開されていることがよくありますが、少なくとも私の経験では、最終的に重要になるいくつかの詳細をざっと読み飛ばし、完全に信頼できるように更新されておらず、場合によっては単に間違っています. ほとんどの場合、それは整理されていないため、見つけられる場所からできることを収集するのはほとんどあなた次第であり、情報が不足している場合 (または忍耐力がある場合) は、不足している部分を埋めるためにリバース エンジニアリングを行います。

編集: Qt ライブラリのような COM 以外のものについては、いくつかの選択肢があります。1 つは、Qt ライブラリに静的にリンクすることです。これにより、必要な Qt コードが実行可能ファイルに直接リンクされます。DLL を使用したい場合は、アプリケーション自体を生成するために使用するコンパイラに固有の DLL をアプリと共に配布することにかなり苦労しています。異なるコンパイラ (または同じコンパイラの異なるバージョンまたはコンパイル フラグのセット) は、通常、異なる DLL (おそらく同じソース コードですが、コンパイラの変更に対応するために構築されています) を必要とします。

これには例外もありますが、上で概説したのとほとんど同じです。たとえば、Windows 用の Intel コンパイラは通常、Microsoft の標準ライブラリを使用し、Microsoft のコンパイラ用に構築された他のライブラリのほとんど (すべてではないにしても) を使用できます。これは、Intel が Microsoft と同じ呼び出し規則、名前マングリング スキームなどを使用することを保証するために、Intel が後方に曲がったためです。それが機能するのは、彼らがそれを機能させるために多くの努力を払ったからであり、不文律やそのようなもののためではありません.

于 2012-05-25T23:04:39.180 に答える
3

DirectX は COM ベースのテクノロジであるため、C でさまざまなコンパイラと共に使用できます。内部の COM インターフェイスは、VMT をエミュレートする C に似た構造です。

技術的には、DirectX には中間自動生成された C++ インターフェイスがありますが、異なるコンパイラ間で .dll にエクスポートされたクラスを使用できるという一般的な主張は間違っています。

編集1:

残念ながら、MSVC を使用してビルドされた QT dll は、gcc によってビルドされたものと互換性がありません。これは、自然な理由によるものです: 異なる C++ コンパイラ - 異なる ABI および異なるランタイム ライブラリ (mingw は古い MSVCRT を使用し、それが pure-C . dll は MSVC で使用でき、その逆も可能です)。一部のコンパイラは、偶然または部分的に意図的に ABI を一致させますが、これは MSVC/gcc には当てはまりません。QT は静的ライブラリとして構築することもできるので、静的にリンクするだけで再配布できます。

DLL 内の C++ クラスの名前マングリングは、使用するコンパイラ フロントエンドに大きく依存します。よく知られている企業の多くの商用コンパイラは EDG の C++ パーサーを使用しており、オーバーロードされた関数のクラス名が類似または一致するシグネチャを持っているのはそのためです。

編集2:

「異なるコンパイラでコンパイルされた 2 つの異なるライブラリを使用したい場合はどうすればよいですか?」

両方のライブラリの特定の機能がどうしても必要な場合 (つまり、フレームワーク全体ではなく、具体的な操作を意味します)、ライブラリのソース コードを持たない方法は、ラッパーを作成し、このラッパーを C スタイルの .dll にコンパイルすることです。 .

これは、「2 つの異なる C++-es、C++-1 と C++-2」があるようなものだと考えてください。ABI/Runtime の問題は、C から Pascal コードを使用したり、古い Fortran ライブラリとリンクしたりする場合と同じです。

于 2012-05-25T23:00:57.370 に答える