シナリオはこうです。C API から C++ へ (静的メソッドを介して) コールバック関数に値で渡されると、構造体が破損するのを見ています。
ライブラリ A: gcc でビルドされた C ベースの API ライブラリ B: g++ でビルドされた C++ ベースの API
ライブラリ A は、-fPIC を使用して静的ライブラリとしてビルドされます。ライブラリ B は、同じく -fPIC でビルドされたライブラリ A をリンクする共有ライブラリとしてビルドされます。
ライブラリ A で定義されている構造体は次のとおりです。
typedef struct doomed_struct
{
uint32_t field1;
uint32_t field2;
CHILD_STRUCT1 field3;
CHILD_STRUCT2 field3;
} DOOMED_STRUCT;
およびコールバック関数:
typedef void (_CALLBACK_FUNC *FUNCTION)(uint32_t arg1, uint8_t arg2,
uint8_t arg3, DOOMED_STRUCT arg4);
C++ API には、クラスで定義された静的メソッドがあり、コールバックのためにこれを C API に渡します。このコールバックが呼び出されると、単純な型指定された arg1、2、3 でうまくいきますが、構造体のフィールドはガベージであり、実行のたびに変化します。
C++ API の関数も静的関数に変更しようとしましたが、extern "C"
うまくいきません。
C API で C 関数をスタブ化し、テストのためだけに呼び出した場合、構造体は破損することなく問題なくコピーされます。
イライラする部分は?これはすべて、Linux および QNX 上の MSVC8/9/10、gcc 4.4.x (32 および 64 ビット) で正常に動作します。数年前に gcc 4.1 に戻ると、これが表示されます。
コピーではなくポインターを介して構造体を渡すようにコールバック関数を変更すると、正常に動作します。残念ながら、C API には ABI の制限があり、変更することはできません。
ある種の呼び出し規則または構造体レイアウトの問題のようなにおいがしますが、このようなもののためにどのノブを回せばよいかわかりません。全体として、構造体は 16 バイトであるため、スタックの問題が発生することはありません。