バックグラウンド:
Windows COM オブジェクトに接続しています。
使用される方法は vtable の変更です。instanceという名前のインターフェイス Aのインスタンスがあり、インターフェイスにoldmethodが含まれているとします。これをnewmethodに置き換えました。ただし、私のnewmethodでは、oldmethodのアドレスを知る必要があります。これにより、独自の処理を行った後に oldmethodを呼び出すことができます。
インターフェース A の背後に複数の実装がある可能性があるため、oldmethodのアドレスをグローバル変数に格納することは安全ではありません。たとえば、クラス A1とクラス A2の 2 つの実装があるとします。したがって、私のnewmethodは A1- >oldmethodとA2->oldmethodの両方を格納し、インスタンス タイプに基づいて適切な関数を呼び出す必要があります。
これを達成する 1 つの方法は、(vtable のアドレス -> oldmethod) を格納するマップを保持することです。vtable のアドレスは、クラス A1 とクラス A2 の区別として機能するためです。私のnewmethodでは、現在のインスタンスの正しいoldmethodについてマップがチェックされます。ただし、これにより、プログラムは毎回マップをチェックするようになり、コストがかかります。また、マップのスレッド セーフはコストを増加させます。
もう 1 つの方法は、クロージャを作成することです。実行可能メモリのチャンクを割り当て、内部にnewmethodのバイナリ コードを書き込みます (最小サイズに縮小できるため、サイズは問題になりません)。各インスタンスのバイナリ コードでoldmethodのアドレスを変更します。この場合、マップ コストでの検索はありません。
質問 1 :
2 番目の方法はこれを行う安全な方法ですか、それとも最初の方法の方が優れていますか? それらのいずれかに潜在的な安全上の問題はありますか?
質問 2 :
2 番目の方法では、作成したクロージャーにクラス固有のデータ (oldmethod ポインター) が含まれています。インスタンス固有のデータをnewmethodに保存する必要がある場合、(this pointer -> data) マップを保持する以外の戦略はありますか? 私は最善を尽くしましたが、方法が見つかりませんでした。