17

ここで説明したものと似ていますが、微妙に異なる問題があります(アセンブリとその依存関係の読み込み)。

顧客に販売する 3D レンダリング用の C++ DLL があります。.NET ユーザーの場合は、CLR ラッパーを使用します。C++ DLL は 32 ビット バージョンと 64 ビット バージョンの両方でビルドできますが、これは、CLR が特定の DLL にバインドされるため、2 つの CLR ラッパーが必要であることを意味すると思いますか?

ここで、顧客が 32 ビットまたは 64 ビットの .NET アプリを持っていて、それが純粋な .NET アプリであるため、単一のアセンブリ セットからそれを解決するために CLR を離れるとします。問題は、アプリ コードが実行時に 32 ビットと 64 ビットの CLR/DLL の組み合わせを動的に選択するにはどうすればよいかということです。

さらに具体的には、前述の質問に対する提案された回答はここでも適用できますか (つまり、ResolveEvent ハンドラーを作成します)?

4

3 に答える 3

8

私はついにこれに対する答えがうまくいくように見えます。

32ビットバージョンと64ビットバージョンの両方(マネージドバージョンとアンマネージドバージョンの両方)を別々のフォルダーにコンパイルします。次に、実行時に.NETアプリにアセンブリのロード元のディレクトリを選択させます。

ResolveEventを使用する際の問題は、アセンブリが見つからない場合にのみ呼び出されることです。そのため、誤って32ビットバージョンになってしまう可能性があります。代わりに、適切なフォルダーを指すようにApplicationBaseプロパティを変更できる2番目のAppDomainオブジェクトを使用します。したがって、次のようなコードになります。

static void Main(String[] argv)
  {
     // Create a new AppDomain, but with the base directory set to either the 32-bit or 64-bit
     // sub-directories.

     AppDomainSetup objADS = new AppDomainSetup();

     System.String assemblyDir = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
     switch (System.IntPtr.Size)
     {
        case (4): assemblyDir += "\\win32\\";
           break;
        case (8): assemblyDir += "\\x64\\";
           break;
     }

     objADS.ApplicationBase = assemblyDir;

     // We set the PrivateBinPath to the application directory, so that we can still
     // load the platform neutral assemblies from the app directory.
     objADS.PrivateBinPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);

     AppDomain objAD = AppDomain.CreateDomain("", null, objADS);
     if (argv.Length > 0)
        objAD.ExecuteAssembly(argv[0]);
     else
        objAD.ExecuteAssembly("MyApplication.exe");

     AppDomain.Unload(objAD);

  }

最終的に2つのexeが作成されます。通常のアプリと、ロードするビットを選択する2番目のスイッチングアプリです。注-私はこれの詳細を自分で信用することはできません。私の同僚の一人は、私の最初の指針を与えられてそれを議論しました。彼がStackOverflowにサインアップした場合、私は彼に答えを割り当てます

于 2009-01-26T12:42:19.303 に答える
3

約1年前にこれを行うことができましたが、詳細をすべて覚えていません. 基本的に、IntPtr.Size を使用してロードする DLL を決定し、p/Invoke を介して実際の LoadLibrary を実行できます。その時点で、メモリ内にモジュールがあり、その内部から p/Invoke 関数を実行できるはずです。同じモジュール名が再度読み込まれることはありません。

ただし、私のアプリケーションでは、実際に C++ DLL を COM サーバーとして登録し、生成された .NET ラッパーを介してその機能にアクセスしたと思います。そのため、p/Invoking を直接テストしたことがあるかどうかはわかりません。

于 2008-08-22T13:53:12.893 に答える
1

しばらく前に同様のシナリオに遭遇しました。私が使用していたツールキットは 64 ビット環境で適切に動作せず、アセンブリを動的に強制的に 32 ビットとしてバインドする方法を見つけることができませんでした。

アセンブリを強制的に 32 ビット モードで動作させることは可能ですが、これには CLR ヘッダーにパッチを適用する必要があり (フレームワークにはそれを行うツールがあります)、アセンブリに厳密な名前が付けられている場合、これは機能しません。

残念ながら、32 ビット プラットフォームと 64 ビット プラットフォーム用に 2 セットのバイナリをビルドして公開する必要があります。

于 2008-08-22T13:30:52.090 に答える