.NET(C#)dllからのpinvokeを使用して、ネイティブdllを呼び出しています。ここで、.NET dllを「AnyCPU」としてコンパイルしたいのですが、「pinvoking」するときは、32ビットまたは64ビットのdllを呼び出す必要があるかどうかを知る必要があります。両方のバージョンのネイティブdllをサブフォルダーbin32とbin64にインストールします。DLLがロードされたら、32ビットモードか64ビットモードかを確認し、適切なパスでSetDllDirectoryを呼び出します。SetDllDirectoryを呼び出す場所からの適切な「エントリポイント」を除いて、このアプローチには問題がないようです。ネイティブDLLには、DLLがプロセスに接続されたときに呼び出されるDllMainエントリがあります。.NET DLLに同様のエントリポイントがありますか?SetDllDirectoryを動的に呼び出すのは良い考えだと思いますか?
2 に答える
.NET には DllMain() 関数に相当するものがあります。これはモジュール初期化子と呼ばれます。ただし、C# および VB.NET コードからは手の届かないところにあり、IL または C++/CLI でしか作成できません。C++/CLI 自体にはビット依存性があるため、IL のみが残ります。この回答でサンプルコードを見つけることができます。アセンブリにリンクするのはかなり面倒です。ビルド システムは、アセンブリ リンカーの実行を直接サポートしていません。
次善の策は、同じ記事で言及されている「型初期化子」であり、C# では静的コンストラクターと呼ばれます。これらを効果的に行うには、コードに組織の類似性が必要です。これは、「数千のメソッド」の 1 つが呼び出される前に使用されることが保証されているクラスです。これだけの方法では難しいはずです。
アプリの Main() メソッドで呼び出さなければならない初期化メソッド以上のものはありません。そしてもちろん、標準的なソリューションである 2 つのインストーラ (1 つは 32 ビット マシン用、もう 1 つは 64 ビット マシン用) です。また、これにより、アプリが「正しい」ディレクトリ、c:\program files と c:\program files (x86) に確実に配置されます。
更新: .NET 5 は、 [ModuleInitializer] 属性を持つ C# v9 のモジュール初期化子をサポートするようになりました
基本的に、あなたが求めているのは、アセンブリが最初に読み込まれたときに実行されるコードを記述できるかどうかです。その質問はここで対処されます: .Net: アセンブリが読み込まれるときにコードを実行する
あなたの立場では、私はあなたのライブラリのユーザーに責任を負わせます。ライブラリを初期化する関数を提供し、ライブラリのユーザーに他の関数の前にそれを呼び出すように依頼します。
必要に応じて、遅延初期化を使用してライブラリ内でその初期化を行うことができます。したがって、すべてのメソッドは次のようになります。
private static void EnsureInitialized()
{
if (!MyLibraryInitialized)
InitializeMyLibrary();
}
public static void DoSomething()
{
EnsureInitialized();
.... // implementation of DoSomething
}
また、使用しないことをお勧めしSetDllDirectory
ます。もっと簡単な方法があります。InitializeMyLibrary()
ロードする必要がある DLL へのフル パスを取得できるため、 を呼び出してロードするだけLoadLibrary()
です。DLL がロードされると、p/invokes は既にロードした DLL に自動的にバインドされます。