MSDNのドキュメントで、VB.NETプログラム内から外部DLLの関数への参照を宣言する 方法が複数あることに気付きました。
紛らわしいのは、MSDNが共有関数プロトタイプでのみDllImportAttributeクラスを使用できると主張していることですが、代わりにキーワードを使用するだけで、このステートメントの説明が見つかりませんでした。Declare
これらが異なるのはなぜですか。また、それぞれのケースをどこで適切に使用しますか?
どうやら、DeclareステートメントとDllImportステートメントは基本的に同じです。お好きな方をお使いいただけます。
以下は、それぞれで少し異なる働きをする可能性のあるいくつかのポイントの説明です。これは、一方の優先度に影響を与える可能性があります。
VisualStudio2003に関するMSDNの記事「DllImport属性の使用」から始めました。(少し古いですが、DllImportステートメントは.NETで作成されたように見えるため、最初に戻るのが適切であるように見えました。)
次のDllImportステートメントの例を考えます。
[DllImport("user32.dll", EntryPoint = "MessageBox", CharSet = Unicode)]
int MessageBox(void* hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned int uType);
EntryPoint値が省略されている場合、CLRはデフォルトとして関数の名前(この場合はMessageBox)を検索することを示しています。ただし、この場合、UnicodeのCharSetが指定されているため、CLRは最初に「MessageBoxW」という関数を探します。「W」はUnicodeの戻り型を示します。(ANSI戻りタイプのバージョンは「MessageBoxA」になります。)「MessageBoxW」が見つからなかった場合、CLRは実際には「MessageBox」と呼ばれるAPI関数を探します。
DllImportAttributeクラスに関する現在の詳細は、ここで見つけることができます。ここでは、.NETFramework4バージョンを表示しました。DLLImportAttributeクラス
この.NETFramework4ページの備考セクションの重要なコメントは次のとおりです。
この属性は、C#およびC++メソッド定義に直接適用します。ただし、Declareステートメントを使用すると、VisualBasicコンパイラはこの属性を発行します。
したがって、VB.NETでは、Declare
ステートメントを使用すると、コンパイラーは。を生成しDLLImportAttribute
ます。
このページには重要な注意事項もあります。
DllImportAttributeは、ジェネリック型のマーシャリングをサポートしていません。
Declare
したがって、ジェネリック型を使用する場合は、ステートメントを使用する必要があるように思われます。
次に、Declareステートメント情報に向かいました。Visual Studio 2010バージョン(Visual Basicステートメント情報)はここにありました:宣言ステートメント
ここでの重要な項目はこのメモでした:
宣言はモジュールレベルでのみ使用できます。つまり、外部参照の宣言コンテキストは、クラス、構造、またはモジュールである必要があり、ソースファイル、名前空間、インターフェイス、プロシージャ、またはブロックにすることはできません。
明らかに、クラス、構造、またはモジュールの外部でAPI呼び出しを設定する場合は、の代わりにDllImportステートメントを使用する必要がありますDeclare
。
Declare
このページのステートメントの例は次のとおりです。
Declare Function getUserName Lib "advapi32.dll" Alias "GetUserNameA" (
ByVal lpBuffer As String, ByRef nSize As Integer) As Integer
その例に続いて、このちょっとした情報があります。
DllImportAttributeは、アンマネージコードで関数を使用する別の方法を提供します。次の例では、Declareステートメントを使用せずにインポートされた関数を宣言します。
もちろん、DllImportの使用例が続きます。
UnicodeとANSIの結果に関して、このDeclareページによると、CharSet値(Declareで使用可能ですが、上記の例には示されていません)を指定すると、CLRはDllImportが実行するのと同じタイプの自動名前検索を実行します-UnicodeまたはANSI。
ステートメントでCharSet値を指定しない場合はDeclare
、Declareの関数名が実際のAPI関数のヘッダーファイルの関数名と同じであることを確認するか、Alias
実際の関数と一致する値を指定する必要がありますヘッダーファイル内の名前(上記の例に示されているように)。
上記以外の状況では、DllImportまたはDeclareのいずれかが相互に優先される、または推奨されることを示す特定のMicrosoftドキュメントを見つけることができませんでした。
したがって、私の結論は次のとおりです。
Declare
ステートメントを使用できない場所の1つに定義を配置する必要がない限り、どちらの手法でも問題なく機能します。と
Declare は実際には、 VB.NETに変換する Visual Basic 6.0 ユーザーにとってより馴染みのあるP/Invoke構文を維持しようとする試みです。これには P/Invoke と同じ機能が多数ありますが、特定の型 (特に文字列) のマーシャリングは大きく異なり、DllImport 規則に慣れている人には少し混乱を招く可能性があります。
ドキュメントが「まれな」区別で何をほのめかしているのか、私には完全にはわかりません。VB.NET と C# の両方から問題なくコードで DllImport を頻繁に使用しています。
一般に、Visual Basic 6.0 の経験がない限り、Declare ではなく DllImport を使用します。DllImport のドキュメントとサンプルははるかに優れており、DllImport 宣言の生成を目的としたツールが多数あります。
私の意見では、このキーワードは私が検索したものから逸脱しているようには見えないので、属性ではなくコンパイル時のキーワードを使用するだけです。
また、を使用する場合はDeclare
、を記述する必要はありませんEnd Function
。その利点は、関数インポートの宣言のモジュール全体を1行ずつ作成できることであり、コードをDllImport
sとEnd Function
sでプルする必要はありません。
キーワードを使用して宣言するDeclare
と、コンパイラはこの関数をShared
とにかく処理するため、他の外部オブジェクトを介してアクセスできます。
しかし、現在のVB.NETでは、両方とも同じターゲットに対応しており、パフォーマンスの違いはないと思います。これに対する保証はありません。
したがって、私の結論は次のとおりです。DllImportの代わりにDeclareを使用してください。特に、 Microsoftがまれに使用する必要があると述べた引用を読んでください。
次のオプションのいずれかを設定する必要がある場合はDllImportAttribute
属性を使用し、それ以外の場合は を使用しますDeclare
。https://msdn.microsoft.com/en-us/library/w4byd5y4.aspxから
BestFitMapping、CallingConvention、ExactSpelling、PreserveSig、SetLastError、または ThrowOnUnmappableChar フィールドを Microsoft Visual Basic 2005 宣言に適用するには、Declare ステートメントの代わりに DllImportAttribute 属性を使用する必要があります。
上記の参照は .NET 4.5 の記事からのものであるため、これが「Visual Basic 2005」のみに適用されるかどうかは、上記の参照のみでは不明です。ただし、.NET のクラスに固有のこの記事 ( https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(v=vs.110).aspxDllImportAttribute
) も見つけました。 4.5 :
Visual Basic コンパイラは、Declare ステートメントを使用すると、この属性を発行します。BestFitMapping、CallingConvention、ExactSpelling、PreserveSig、SetLastError、または ThrowOnUnmappableChar フィールドを含む複雑なメソッド定義の場合、この属性を Visual Basic メソッド定義に直接適用します。
これは、オプションがコンパイル時にDeclare
変換される VB.net シンタックス シュガーであることを示し、直接使用が推奨される場合の正確なシナリオの概要を示しています。DllImportAttribute
DllImportAttribute