7

Visual Studio c ++ V10を使用して、DLLを構築し、DLLの名前の競合を解決する方法を理解しようとしています。詳細はこちらです。

S社は。という製品を出荷していますM.EXEM.EXEにインストールされていると仮定し\S\BIN\M.EXEます。会社SU.DLLは、にインストールされている、 というDLLに静的にリンクしています\S\BIN\U.DLL。 オープンソースコードが含まれており、wcharをネイティブ型として認識しないU.DLLVisualC++コンパイラオプションを使用して構築されています。/Zc:wchar_t-

C社はと呼ばれるDLLO.DLLを出荷し、このDLLのAPIを公開し、のインポートライブラリを出荷しO.DLLます。O.DLLにインストールされていると仮定し\C\BIN\O.DLLます。 にインストールされている、O.DLLというDLLに静的にリンクします。 は同じオープンソースコードに基づいて構築されていますが、ネイティブタイプとして認識されるVisualC++コンパイラオプションを使用して構築されています。U.DLL\C\BIN\U.DLLU.DLL/Zc:wchar_twchar_t

理想的には、C社とS社U.DLLは同じVisual C ++オプションを使用してビルドすることに同意しますが、それは不可能です。

M.EXES社からは拡張可能であり、アンマネージC ++で独自のDLLを構築できます。これを呼び出すとNODE.DLLM.EXEすべてが正しくセットアップされた場合に呼び出されます。C社からNODE.DLL静的にリンクするようにビルドしたいのですが、問題は、一度実行すると、からライブラリがロードされ、からのシンボルが、それぞれによってどのようにビルドされたかにより、のシンボルとわずかに異なることです。会社。したがって、ロードしようとすると失敗します。これは、をロードするときに、必要なシンボルが存在しないためです。これは、Windowsがすでにロードされていると見なすためです。O.DLLM.EXEU.DLL\S\BIN\S\BIN\U.DLL\C\BIN\U.DLLU.DLLM.EXENODE.DLLNODE.DLLO.DLLU.DLL\C\BIN\U.DLLU.DLL

状況の図は次のとおりです。

M.EXE static link to -> \S\BIN\U.DLL
M.EXE dynamic link to -> NODE.DLL
NODE.DLL static link to  O.DLL
O.DLL static link to \C\BIN\U.DLL

事実上、私はとの両方が同じプロセススペースに共存する必要があり、\S\BIN\U.DLLその\C\BIN\U.DLLバージョンM.EXEのを使用し、そのバージョンのU.DLLO.DLL使用していU.DLLます。

M.EXE再構築したりO.DLL、それぞれの読み込み方法を変更したりするオプションがないことに注意してくださいU.DLL。それらはサードパーティからのものであるため、静的リンクを変更することはできません。また、インポートライブラリが提供されているC ++ライブラリであるため、LoadLibraryonを使用するオプションもありません。O.DLL

マニフェストを使用してNODE.DLL、O.DLLに静的にリンクされたビルドを作成するときに、のマニフェストに設定して、にインストールされている独自のコピーNODE.DLLをロードできると思います。私はこれを行う方法を理解することができません。理想的には、のマニフェストを変更したくないのですが、それが唯一の解決策である場合は、それを使用します。O.DLLU.DLL\C\BIN\U.DLLO.DLL

4

4 に答える 4

4

1つまたは複数のDLLに絶対パスをロードすることにより、同じプロセスで同じファイル名の複数のDLLを作成できます。これにはDLLを動的にロードする必要がありますが、それ以外の動作は同じです。

ビルドプロセス中にリンクする代わりに、する必要がありますstd::string moduleName = appPath + "\s\bin\u.dll"; LoadModule(moduleName.c_str())。これはどのDLLをロードする必要があるかについて明確であるため、「同じ」名前で複数のDLLをロードすることができます。

モジュールをロードしたら、必要な各関数を関数ポインターに割り当て、それらをラップするか、関数ポインターを通常の関数として呼び出すという、正当ではあるがほとんど使用されていない構文を使用できます(funcPtr(params))。

最新バージョンのWindowsを使用している場合は、DLLマニフェストを使用して、モジュールのバージョン管理/名前付けを強化し、EXEに通常とは異なるDLLをロードさせることができる場合があります。これがどのように行われるのかはよくわかりませんが、MSDN(およびおそらくここでも)に文書化されています。

于 2013-01-11T15:41:08.577 に答える
1

/delayload リンカー オプション (VS プロジェクト プロパティの [リンカー]、[入力]、[遅延ロードされた DLL]) をカスタム フックと共に使用することで、実行時にソース DLL をプログラムで解決できます。ソース ファイルの 1 つで、delayload フック関数を定義して登録する必要があります。フック関数の dliNotePreLoadLibrary 通知ハンドラーで、目的の DLL への明示的なパスを指定して LoadLibrary を呼び出すだけで、DLL の HMODULE を delayload コードに戻します。delayload コードは、同じ名前の別の DLL が既にプロセスにロードされているかどうかに関係なく、インポートされた関数を指定した DLL に解決します。

私の頭の上では、フックは次のようになります ( MyCustomLoadLibrary は、競合する場合は目的の DLL への完全なパスを指定して LoadLibrary を呼び出すコードに置き換える必要があり、それ以外の場合は修飾されていないファイル名のみを指定する必要があります)。

#include <delayimp.h>
FARPROC WINAPI MyDliNotifyHook( unsigned dliNotify, PDelayLoadInfo pdli )
{
  if( dliNotify == dliNotePreLoadLibrary )
    return (FARPROC)MyCustomLoadLibrary( pdli->szDll );
  return NULL;
}
extern "C" PfnDliHook __pfnDliNotifyHook2 = MyDliNotifyHook;
于 2013-01-14T05:23:13.360 に答える
0

U.DLL がオープン ソースであることは幸運です。と関数の両方をサポートするバージョンをビルドする必要があります。最初のオプションは単に として定義します。引数を持たない関数ごとに、シンボルの重複に関する大量のリンカー警告が表示されますが、それ以外の場合は、DLL が肥大化するだけです。/Zc:wchar_t-/Zc:wchar_twchar_t-unsigned shortwchar_t

を使用するグローバル変数またはstatic変数がある場合wchar_tは、それらのコピーも 2 つ作成されます。しかし、1 つのプロセスで の 2 つのコピーを押し込めば、同じ効果が得U.DLLられます。

于 2013-01-14T07:56:23.943 に答える
0

LoadLibrary と GetProcAddress を使用してみてください。ただし、これには、どこでも関数ポインターを使用するようにコードを再構築する必要があります。見る:

LoadLibrary の MSDN Web ページ

于 2013-01-11T15:42:37.273 に答える