11

たとえば、共有ライブラリに対応する次のヘッダーファイルを想定します。エクスポートされた関数は、このヘッダーで定義されたカスタム構造へのポインターを取ります。

// lib.h

typedef struct {
  char c;
  double d;
  int i;
} A;

DLL_EXPORT void f(A* p);

共有ライブラリが1つのコンパイラを使用して構築され、別のコンパイラで構築されたCコードから使用される場合、C構造体のメモリアライメントが示唆するように、メモリアライメントが異なるために機能しない可能性があります。それで、同じプラットフォーム上の異なるコンパイラ間で構造定義を移植可能にする方法はありますか?

私は特にWindowsプラットフォームに興味があります(明らかに、明確に定義されたABIがありません)が、他のプラットフォームについても知りたいと思います。

4

3 に答える 3

13

TL;DR 実際には問題ないはずです。

これは C 標準では定義されていませんが、プラットフォーム ABI では一般的に定義されています。つまり、特定の CPU アーキテクチャとオペレーティング システムに対して、異なるコンパイラが相互運用できるようにするアセンブリへの C のマッピング方法の定義が存在する可能性があります。

プラットフォーム ABI が定義しなければならないのは構造体のアライメントだけではありません。関数呼び出し規約なども必要です。

C++ ではさらに複雑になり、ABI は vtables、例外、名前マングリングなどを指定する必要があります。

Windows では、コンパイラに応じて複数の C++ ABI があると思いますが、C はコンパイラ間でほぼ互換性があります。Windows の専門家ではなく、私が間違っている可能性があります。

いくつかのリンク:

とにかく肝心なのは、C標準ではなく、プラットフォーム/コンパイラのABI仕様で保証を探しているということです。

于 2012-04-24T13:20:44.320 に答える
4

確実に知る唯一の方法は、問題のコンパイラのドキュメントを参照することです。ただし、通常、C struct レイアウト (ビットフィールドを除く) は、使用している環境の ABI 記述によって定義され、C コンパイラはネイティブ ABI に従う傾向があります。

于 2012-04-24T13:22:29.607 に答える
1

保証されていないだけでなく、同じコンパイラを使用していても、ビルドで使用されているコンパイラ スイッチが異なるため、または同じコンパイラと同じスイッチの異なるバージョンを使用している場合 (組み込みコンパイラで発生した取り組んだ)。

構造体がまったく同じように表現されていることを確認する必要があります。コンパイラが提供するものは何でも、スイッチ、#pragmas を使用してください。

私のアドバイスは、これから完全に離れることです。構造体にラップするのではなく、引数を関数に渡します。

そして、この単純な形式でも、2 つのコンパイラーを扱う場合は簡単ではありません。たとえば、int が同じバイト数であることを確認する必要があります。また、conevntion の呼び出し (引数の順序 - 左から右または右から左) は、コンパイラ間で異なる場合があります。

于 2012-04-24T13:20:35.093 に答える