0

静的ライブラリにC関数があります。これをAと呼びましょう。次のインターフェイスを使用します。

int A(unsigned int a, unsigned long long b, unsigned int *y, unsigned char *z);

この関数はyazの値を変更します(これは確かです)。extern "C"を使用して、動的C++ライブラリ内から使用します。

さて、これが私を驚かせるものです:

  • yは正しく設定され、zは変更されません。私が正確に意味するのは、両方が666の(ポイントされた)値で初期化された場合、yがポイントした値は呼び出し後に変更されますが、zがポイントした値は変更されません(まだ666)。
  • Cバイナリから呼び出されると、この関数はシームレスに機能します(zが指す値が変更されます)。
  • 同じプロトタイプを持つ関数を使用してダミーのCライブラリを作成し、それを動的C ++ライブラリ内から使用すると、非常にうまく機能します。同じ変数を再利用してA(..)を呼び出すと、以前と同じ結果が得られます。zは変更されません。

上記の点は、私の変数の宣言が愚かな間違いではないことを示していると思います。

明らかに行き詰まっていて、Cライブラリを変更できません。何が問題になるのか、何か手がかりはありますか?私はC/C ++インターフェースの問題、たとえばchar*の解釈方法について考えていました。

編集:私はついに何が問題だったのかを見つけました。以下の私の答えを参照してください。

4

10 に答える 10

4

C ライブラリと C++ コンパイラがlong longsを処理する方法の違いのようです。私の推測では、C ライブラリはおそらく C89 標準より前であり、実際には 64 ビットの長さを 32 ビットの長さとして扱っています。C++ ライブラリはそれを正しく処理し、コール スタックに 64 ビットを配置しているため、y と z が破損しています。*int A(unsigned int a, unsigned long b, unsigned int *y, unsigned char z)を介して関数を呼び出してみて、何が得られるかを確認してください。

ちょっとした考え。

于 2008-09-29T10:00:17.983 に答える
2

これは、あなたが説明したことから明らかに間違っていることは何もないにもかかわらず、物事が期待どおりに機能していないという質問の 1 つです。

賢明な回答を得るには、投稿を編集してより多くの情報を提供する必要があると思います。特に、次から始めましょう:-

  • このコードはどのプラットフォーム向けのものですか: Windows、Linux、何かが埋め込まれているか ...?
  • C スタティック ライブラリはどのコンパイラでビルドされていますか?
  • C++ ダイナミック ライブラリはどのコンパイラでビルドされていますか?
  • ビルドされたライブラリを正常に呼び出すことができる C コンパイラは何ですか?
  • ソースレベルのデバッガーはありますか? もしそうなら、C++ から C コードにステップ インできます

A が常に Z が指すデータを変更することについて間違っていない限り、問題の唯一の可能性のある原因は、パラメーターの受け渡し規則間の非互換性です。「長い長い」問題は、物事が見かけどおりではないことを示唆している可能性があります。

最後の手段として、逆アセンブルされた C++ 呼び出しコード (失敗と言う) と C 呼び出しコード (成功と言う) を比較するか、デバッガーを使用して CPU 命令をステップスルーすることができます (はい、本当に - あなたは問題を解決するだけでなく、優れたスキル)

于 2008-09-29T12:11:17.483 に答える
1

私の知る限り、longlongは標準のC++の一部ではなく、おそらくそれが問題の原因です。

于 2008-09-29T09:11:20.877 に答える
1

わからない。デバッグしてみてください-Aにステップインして、何が起こるかを確認してください(アセンブリコードアラート!)

于 2008-09-29T09:14:54.240 に答える
1

まず、皆様のご協力に心より感謝申し上げます。あなたが私に与えてくれた多くのアイデアと手がかりのおかげで、私は最終的にこの問題を解決することができました. あなたのアドバイスのおかげで、私が当たり前だと思っていたことに疑問を抱くことができました。

私の問題に対する簡単な答え: 問題は、私の C++ ライブラリが古いバージョンの C ライブラリを使用していたことです。この古いバージョンでは、4 番目の引数がありませんでした。結果として、4 番目の引数は明らかに変更されませんでした。

これが問題だと気づいた今、私は少し恥ずかしいです。しかし、コードが正常にコンパイルされているという事実に誤解されました。これは、C++ ライブラリが C ライブラリの正しいバージョンに対してコンパイルされたという事実によるものでしたが、実行時には、私が使用していた別のライブラリに静的にリンクされた古いバージョンを使用していました。

C++ Lib (M) ---> dyn C++ lib (N) ---> C lib (P) v.1.0
     |
     ------> C lib (P) v.1.1

(N) は、(P) バージョン 1.0 と静的にリンクされている動的ライブラリです。(P) バージョン 1.1 に対してリンクしたため、コンパイラは (M) から 4 つの引数を持つ関数への呼び出しを受け入れましたが、実行時には古いバージョンの (P) を使用していました。

この回答または質問を自由に編集するか、そうするように依頼してください。

于 2008-09-29T17:00:05.183 に答える
1

Another wild guess: are you sure you're linking against the right instance of the function in your C library? Could it be that there are several such functions available in your libraries? In C the linker doesn't care about the return type or the parameter list when deciding how to resolve a function -- only the name is important. So, if you have multiple functions with the same name...

You could programmatically verify the identity of the function. Create a C library that calls your function A with some test parameters and that works fine and that prints the pointer to function A. Link the library into your C++ app. Then print the pointer to the original A function as seen from the C++ code and compare the pointer with that seen by your C library when invoked in the same process.

于 2008-09-29T12:15:56.537 に答える
1

繰り返しますが、明らかなことですが、呼び出している C 関数がステートレスであり、その出力がその入力のみに依存していることを意味しますか? 関数がステートレスでない場合、zC++ アプリから呼び出されたときの関数の別の動作 ( が指すデータを変更しない) は、"非表示" 状態が原因である可能性があります。

于 2008-09-29T12:24:29.977 に答える
1

C++ ライブラリから呼び出す C ライブラリに元の関数をラップすることはできますか?

ポイント2と3に基づいて、これはうまくいくようです。

そうでない場合は、さらに手がかりを見つけるための別のデバッグ ポイントが提供されます。失敗が最初に表示されるライブラリを確認し、2 と 3 が機能する理由を確認しますが、これは機能しません。最小の違いは何ですか?

それぞれの場合に関数呼び出しによって設定されたスタックを調べて、違いがここにあるかどうかを確認することもできます-異なる呼び出し規則を考慮してください。

于 2008-09-29T09:39:35.897 に答える
1

ステップ 1: C++ 側から渡されたポインター y および z を、C 関数によって受信されたポインターと比較します。

PS 明白に聞こえたくはありませんが、ここで再確認してください。C バイナリから呼び出されたときに z が適切に変更されると言うとき、z が指しているデータが適切に変更されることを意味していると思います。ポインター y と z 自体は値渡しされるため、ポインターを変更することはできません。

于 2008-09-29T09:45:12.873 に答える
0

C ++プログラムでは、プロトタイプは?で宣言されていextern "C"ますか?

于 2008-09-29T09:12:50.093 に答える