4

私はかなり長い間ダイナミックライブラリとGetProcAddressのものを使用してきましたが、それは常に退屈で、インテリセンスの敵対的で、物事を行うための醜い方法のようです。

古いOSとの互換性を維持しながら、新しい機能をインポートするためのクリーンな方法を知っている人はいますか。

Vistaの一部であるXMLライブラリを使用したいとします。LoadLibraryWを呼び出し、HANDLEがnullでない場合は、関数を使用できます。

しかし、私は本当に行きたくありません、#typedef (void*)(PFNFOOOBAR)(int, int, int)そしてPFNFOOOBAR foo = reinterpret_cast<PFNFOOOBAR>(GetProcAddress(GetModuleHandle(), "somecoolfunction"));、その間ずっと50、方法。

この混乱を避けることができる非ハックな解決策はありますか?

プロジェクト設定にcoolxml.libを追加してから、delayload dllリストにcoolxml.dllを含め、必要なファイルで使用するいくつかの関数シグネチャをコピーすることを考えていました。次に、LoadLibraryWがnull以外で返されることを確認し、nullでない場合は、通常のプログラムフローのようにVistaブランチに分岐します。

しかし、LoadLibraryとdelay-loadが連携して機能するかどうか、また、分岐予測によって問題が発生しない場合があるかどうかはわかりません。

また、このアプローチが機能するかどうか、および次のSDKにアップグレードした後に問題が発生しないかどうかもわかりません。

4

3 に答える 3

4

IMO、LoadLibrary、およびGetProcAddressは、これを行うための最良の方法です。

(それを処理するラッパーオブジェクトをいくつか作成して、メインコードをそのロジックと醜さで汚染しないようにします。)

  1. DelayLoadはセキュリティの問題をもたらします(このOldNewThingの投稿を参照)(編集:古いバージョンのWindowsでこれらのAPIを呼び出さないようにする場合はそうではありません)。

    また、DelayLoadを使用すると、すべてのターゲットで使用できないAPIに誤って依存する可能性が高くなります。はい、ツールを使用して実行時に呼び出すAPIを確認できますが、コンパイル時、IMOでこれらを処理することをお勧めします。これらのツールでは、実際に実行するコードのみを確​​認できます。

  2. また、コードとコードとの間で受け渡されるオブジェクトを分離することに細心の注意を払っていない限り、コードの一部を異なるWindowsヘッダーバージョンでコンパイルすることは避けてください。

    それは絶対に間違っているわけではありません-プラグインDLLのように、2つのまったく異なるチームがお互いにどのSDKバージョンをターゲットにしているかを知らずに、おそらく2つのモジュールで作業した場合は完全に正常です-しかし、そうでない場合は難しい問題につながる可能性があります注意するので、一般的には避けるのが最善です。

    ヘッダーバージョンを混在させると、非常に奇妙なエラーが発生する可能性があります。たとえば、Vistaでサイズが変更されたOS構造を含む静的オブジェクトがありました。プロジェクトのほとんどはXP用にコンパイルされましたが、名前がたまたまAで始まり、Vistaヘッダーを使用するように設定された新しい.cppファイルを追加しました。その新しいファイルは、(任意に)Vista構造サイズを使用して静的オブジェクトの割り当てをトリガーするファイルになりましたが、そのオブジェクトの実際のコードはXP構造を使用してビルドされました。コンストラクターは、オブジェクトのメンバーが、オブジェクトを割り当てたコードとは異なる場所にあると考えました。奇妙なことが起こりました!

    その根底に到達すると、私たちはその慣習を完全に禁止しました。プロジェクト内のすべてがXPヘッダーを使用し、新しいヘッダーから何かが必要な場合は、手動でコピーして、必要に応じて構造の名前を変更します。

すべてのtypedefとGetProcAddressのものを記述し、ヘッダーから構造と定義をコピーするのは非常に面倒です(これは間違っているように見えますが、バイナリインターフェイスなので、変更されません)(#pragmaを確認することを忘れないでください)パックも:()ですが、コンパイル時に問題を通知するのに最適な方法はIMOです。

他の人はきっと反対するでしょう!

PS:GetProcAddressのものを少し面倒なものにするために作成した小さなテンプレートがどこかにあります...それを見つけようとしています。私がそうするとき/もしそうなら、これを更新します。見つけましたが、実際にはそれほど役に立ちませんでした。実際、私のコードはどれもそれを使用していませんでした。:)

于 2010-12-10T10:40:51.110 に答える
2

はい、遅延ロードを使用します。それはコンパイラに醜さを残します。もちろん、XPでVista関数を呼び出していないことを確認する必要があります。

于 2010-12-10T09:46:30.020 に答える
1

遅延ロードは、直接使用LoadLibrary()を避けるための最良の方法です。GetProcAddress()上記のセキュリティ問題に関して、あなたができる唯一のことは、遅延ロードフックdliNotePreLoadLibraryを使用して、アプリに関連するのではなく、正しいシステムパスを使用して通知中に目的のDLLがロードされていることを確認する(そしてオプションで強制する)ことですフォルダ。コールバックを使用すると、目的のAPI関数が使用できない場合に、 dliFailLoadLib/通知で独自のフォールバック実装を置き換えることもできます。dliFailGetProcそうすれば、コードの残りの部分でプラットフォームの違いを心配する必要がなくなります(またはほとんど気になりません)。

于 2011-04-02T05:47:23.047 に答える