6

多くの COM オブジェクトを含む巨大な C++ コードベースがあります。COM に公開される各関数には__stdcall呼び出し規約 (通常はSTDMETHODCALLTYPEマクロ) が必要なため、多くの関数が とマークされていますSTDMETHODCALLTYPE

ここで、COM を介して直接呼び出されたのではなく、C++ コード内からのみ呼び出された関数を確認しました。この関数STDMETHODCALLTYPEのシグネチャにもマクロが含まれています。マクロが役に立たないことは完全に確信しています.COMを介してその関数を呼び出すことはありません。

__stdcall「デフォルト」の呼び出し規約関数になるように削除する必要がありますか? どうすればそのような決定を下せますか?

4

5 に答える 5

9

私のアプローチは、内部コードには既定のコンパイラ呼び出し規則を使用し、モジュールの境界を越えてエクスポートされるメソッドには明確に定義された明示的な呼び出し規則を使用することです。

ほとんどのコンパイラのデフォルトの呼び出し規約では、パフォーマンス上の理由からレジスタをうまく利用しているため、必要に応じてレジスタを使用する利点があります。また、デフォルトを取得するために規則を指定する必要がないため、コードが見やすくなります。

エクスポートされた関数の場合、規則を明確に指定する必要があります。C または C++ 以外の言語から呼び出されることが予想されるライブラリを作成している場合は、stdcall を使用するのが一般的です。C または C++ クライアントのみを想定している場合は、おそらく cdecl が最も一般的な規則です。

于 2011-05-03T14:05:32.497 に答える
5

Windows が既定の呼び出し規約として __ cdecl から _ _stdcall に切り替えたとき、製品のサイズは約 10% 減少しました。その節約は、stdcall メソッドを呼び出した後にスタック調整を削除することに完全に関連していました (__cdecl は「呼び出し元がパラメーターを削除するためにスタックを調整する」呼び出し規約であり、__stdcall は「呼び出し先がパラメーターを削除するためにスタックを調整する」呼び出し規約です。呼び出し先よりも呼び出し元を切り替えると、バイナリのサイズが縮小されます)。

__stdcall を使用することの欠点は、引数の変数番号がないことです (呼び出し先がスタックを調整するため、呼び出し元が指定したパラメーターの数を知ることができません)。

結論: 「デフォルト」の呼び出し規約から __stdcall に切り替えると、バイナリのサイズが小さくなる可能性があります。それはあなたにとって重要かもしれませんし、そうでないかもしれません。

ただし、上記の mkaes のように、コードがのコンパイル環境でアクセスされることがない場合 (たとえば、.lib ファイルを他の人に配布する場合)、使用する呼び出し規約を宣言することが絶対に重要です。

于 2011-05-03T15:09:24.093 に答える
3

COM スタッフが呼び出し規約を明示的に設定する唯一の理由は、それが DLL の境界を越えて使用されるためです。
したがって、呼び出し規約の明示的な設定を削除し、コンパイラの設定で設定することをお勧めします。
一般的
に: 関数が DLL としてエクスポートされる場合は、ヘッダーで呼び出し規約を定義するマクロを設定します。これにより、ユーザーが DLL にリンクするときに、DLL のユーザーが間違った呼び出し規則を使用するのを防ぐことができます。明示的にコンパイラ設定をオーバーライドします。
ローカル関数で呼び出し対流を使用しないでください。規則は、コンパイラ スイッチによって設定できます。明示的に設定する場合は、すべての関数で行います。その後、呼び出し規約を変更するための中心的な場所がまだあります。
もちろん、それが理にかなっている場合や、最適化のために fastcall などの特別な呼び出し規約が必要な場合は、明示的に設定する必要もあります。

于 2011-05-03T14:05:42.223 に答える
2

プログラム全体の最適化リンク時のコード生成を有効にしていますか? その場合、関数を DLL からエクスポートしたり、関数へのポインターを渡したりしないと、コンパイラはその関数のカスタム呼び出し規約を生成したり、インライン化したりすることがあります (ヘッダー ファイルで定義されていなくても)。

于 2011-05-03T15:11:08.327 に答える
1

ソリューションに関連付けられている ODL ファイルを検索することで、マップが参照されているかどうかを確認できます。そこにない場合は、インターフェイスがなく、呼び出し規約を変更できます。すべての関数がこの呼び出し規則でセットアップされていると他の誰かが想定するリスクがあり、後でインターフェイスを追加する可能性があります。

于 2011-05-03T14:09:04.587 に答える