問題タブ [calling-convention]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
visual-studio-2008 - Visual Studio でカスタム プロローグおよびエピローグ コードを使用してネイキッド関数を作成する
私が制御できないホストによって呼び出される dll に、いくつかのプラグイン コードを書いています。
ホストは、プラグインが __stdcall 関数としてエクスポートされると想定します。ホストは、関数の名前と、それが期待する引数の詳細を通知され、LoadLibrary、GetProcAddress を介して動的に呼び出しを作成し、手動で引数をスタックにプッシュします。
通常、プラグイン dll は一定のインターフェイスを公開します。私のプラグインは、dll の読み込み時に設定されるインターフェイスを公開します。これを実現するために、私のプラグインは、dll のコンパイル時に定義された一連の標準エントリ ポイントを公開し、公開されている内部機能に必要に応じてそれらを割り当てます。
内部関数はそれぞれ異なる引数を取る場合がありますが、これは物理エントリポイント名とともにホストに伝えられます。私の物理的な dll エントリポイントはすべて単一の void * ポインターを取るように定義されており、最初の引数からのオフセットと、ホストに伝達された既知の引数リストを使用して、スタックから後続のパラメーターを自分でマーシャリングします。
ホストは正しい引数を使用してプラグインの関数を正常に呼び出すことができ、すべて正常に動作します...ただし、a) 私の関数は、定義されているはずのようにスタックをクリーンアップしていません。 __stdcall 関数は 4 バイトのポインターを受け取るため、呼び出し元がさらに多くの引数をスタックにプッシュした場合でも、常に最後に 'ret 4' を実行します。b) 戻り時に ret 4 が 4 バイトをスタックからあまりにも多くポップするため、引数を取らない関数を処理できません。
私のプラグインからホストの呼び出しコードまでたどってみると、実際には a) はそれほど大したことではないことがわかります。ホストは、ディスパッチ呼び出しから戻るまでスタックスペースをいくらか失います。その時点で、スタックフレームがクリーンアップされ、ゴミがクリーンアップされます。でも...
b) は __cdecl に切り替えて、まったくクリーンアップしないことで解決できます。a) ネイキッド関数に切り替えて、独自のジェネリック引数クリーンアップ コードを記述することで、a) を解決できると思います。
呼び出されたばかりの関数が使用する引数スペースの量を知っているので、次のように単純になることを望んでいました。
しかし、 ret にはコンパイル時定数が必要なため、それは機能しません...何か提案はありますか?
更新しました:
ロブ・ケネディの提案のおかげで、うまくいくようです...
これは正しく見えますか?
c++ - C / C ++のさまざまな呼び出し規約とは何ですか?それぞれの意味は何ですか?
C / C ++で使用できるさまざまな呼び出し規約があります:、、、stdcall
などextern
。pascal
このような呼び出し規約はいくつ利用できますか。それぞれの意味は何ですか。これらを説明するリンクはありますか?
c++ - C++関数でデフォルトパラメータを最後に追加する必要があるのはなぜですか?
C++関数でデフォルトパラメータを最後に追加する必要があるのはなぜですか?
visual-studio-2008 - VS2003 でコンパイルされた .lib が VS2008 でコンパイルされたコードとリンクできないのはなぜですか?
Visual Studio Express 2008 を使用してコンパイルされた一連のコードを、Visual Studio 2003 でコンパイルされた .lib にリンクしようとしたときに、興味深い経験がありました。すべて C++ です。正確には、VS2003 で .lib にコンパイルされたSystemC 2.2.0 カーネルと、VS2008 でコンパイルされた SystemC モデルでした。
リンク時に、リンク中に SystemC.lib ファイル (つまり、VS2003 でコンパイルされたもの) からいくつかのシンボルが見つからないというエラーが発生し続けました。得られるエラーは次のとおりです(いくつかのバリエーションがあります):
さまざまなリードから掘り下げた結果、.lib が期待する機能は次のとおりであることが判明しました。
VS2008 がリンクしようとしていたライブラリ ファイル (libcpmt.lib) では、別の呼び出し規約が使用されていました。
この非互換性が発生した理由を突き止めようとしましたが、最終的にあきらめて、まったく同じ Visual Studio プロジェクトを VS2008 で再コンパイルし、VS2003 の SystemC.lib の代わりにその SystemC.lib を使用しました。これで、問題なく動作しました。
したがって、ここでの基本的な質問は、VS2003 から VS2008 への変更により、一部の関数の呼び出し規約が変更される原因となるのは何ですか? また、VS2003 コンパイルと同じ呼び出し規則を持つ関数を使用するために、VS2008 のリンカーに与える魔法のフラグはありますか?
更新、これまでの回答の要約: Microsoft が C++ (C ではなく C++ のみ) ABI を Visual Studio のメジャー バージョンから次のメジャー バージョンに変更する可能性が非常に高いです。ライブラリには、非互換性の原因となるその他の変更が含まれている場合もあります。最良のアドバイスは、VS の各バージョンの .lib を再コンパイルすることです。基本的には、ソースでユーザーに出荷し、ユーザーがたまたまインストールした VS のバージョンを使用してローカルでコンパイルするだけです。
基本的な問題は、次のアドバイスを使用して発見されました。
これらの質問はこの問題に答えていないことに注意してください。
c++ - __stdcall の意味と使い方は?
最近、私は__stdcall
多くのことに出会いました。
MSDN は、それが実際に何を意味するのか、いつ、なぜそれを使用する必要があるのかについて、あまり明確に説明していません。
できれば1つか2つの例で、誰かが説明を提供してくれれば幸いです。
c++ - boost::function_types を使用した関数呼び出し規則
最近、boost::function_types ライブラリを試していたところ、ちょっとした障害に遭遇しました。特定の関数の呼び出し規約を知りたいのですが、これを行う方法がよくわかりません。これが私がこれまでに持っているものです:
これにより、各 if ステートメント内で *_cc タグの値が見つからないというエラーが発生します。マクロを定義している方法に関係があるのではないかと思います。ドキュメントは、コンパイラで追加の呼び出し規約を設定する方法についてあまり明確ではありません...ここで何か助けていただければ幸いです。
ありがとう、
編集: 動作しました。以下のように config/config.hpp を含める必要があるようです:
c++ - 以前のバージョンの Visual Studio でビルドされたサード パーティの静的ライブラリとのリンク エラー
私は、サードパーティの静的ライブラリ (ここでは EXTERNALLIB と呼ばれます) にリンクするプロジェクトに取り組んでいます。Visual Studio 2005 では、EXTERNALLIB にリンクして、使用可能な実行可能ファイルを作成することができました。現在、Visual Studio 2008 を使用していますが、次のエラーが表示されます。
EXTERNALLIB に正しくリンクするようにコンパイラに指示する方法はありますか? この問題は、特定の呼び出し規約 (__stdcall、__cdecl、__clrcall、__thiscall) に関連していると思われます。新しいプログラムで古いライブラリの正しい呼び出し規約を示すことはできますか? 今後のコンパイラのアップグレードでこの問題が発生しないように、ベンダーに提供できる特定のフィードバック (ヘッダー ファイルで APIENTRY を使用するなど) はありますか?
コードは C++ で書かれています。EXTERNALLIB のコードにアクセスできないため、自分で再構築することができません。
c - 呼び出し元が cdecl 呼び出し規約でスタックをクリアする必要があるのはなぜですか?
出典: http://en.wikipedia.org/wiki/X86_calling_conventions
呼び出された関数がスタックからパラメーターをポップしてスタックポインターを復元する必要があるため、スタックをクリアするために明示的に ESP に 12 を追加する必要があるのはなぜですか?
別の質問:
理論的には、呼び出し先がクリーンアップ権を処理して変数パラメーター関数を実装することは可能でしょうか (たとえば、スタック上の引数の数をレジスターに渡す場合)。
c# - メソッドを静的にするとパフォーマンスが向上しますか? また、どのような状況でしょうか?
メソッドを非静的にしてインスタンスメンバーを介して同じ値にアクセスするよりも、静的メソッドに引数として引数を渡す方が速い場合はいつですか。メソッドがこれらのメンバーに読み取り専用でアクセスするとします。
他のすべての条件が同じであれば、静的メソッドの呼び出しはインスタンス メソッドの呼び出しよりわずかに高速です。
他のすべての条件が同じであれば、引数なしでメソッドを呼び出すと、引数付きでメソッドを呼び出すよりもわずかに高速です。
検討:
この同等のコードに対して:
この種の最適化が実際に価値を追加する現実世界の状況は考えられませんが、思考実験として (この種のことについて議論したい人向け)、本当に利点があるのでしょうか? もしそうなら、いくつの引数 (どのタイプなど) がバランスを逆に傾けますか?
これを考慮して、他の要因はありますか?たとえば、静的メソッドは_thing
、フィールドではなくローカル変数としてアクセスします。
linux - C 呼び出し規約と渡された引数
Linux (または OS X) で関数呼び出しを行う場合、呼び出し先はスタック上の引数の値を変更できますか? 私は、呼び出し元がそれらをクリーンアップするものであるため、関数呼び出し後に同じ値を含める必要があると想定していました。ただし、-O2 を指定した GCC は、スタック上で渡されたパラメーターを変更していたことがわかりました。System V i386 呼び出し規則を含むドキュメントも探しましたが、これに対する決定的な答えを見つけることができませんでした。
これが私がデバッグしていたサンプルコードです。
スタック上のそのパラメーターを変更するGCCは問題ないと思いますが、それができると指定されている場所を知りたいです。