Domanda

Ho notato nella documentazione di MSDN che ci sono diversi modi per dichiarare un riferimento a una funzione in una DLL esterna da un programma VB.NET.

La cosa confusione è che MSDN sostiene che è possibile utilizzare solo il DllImportAttribute classe con prototipi di funzione condivisa" in rari casi "ma io non riuscivo a trovare la spiegazione di questa affermazione, mentre si può semplicemente utilizzare il Declare parola chiave, invece.

Perché questi diversa, e dove dovrei usare in modo appropriato ogni caso?

È stato utile?

Soluzione

Dichiarare è davvero un tentativo di mantenere un P / Invoke sintassi che sarebbe più familiare a visual Basic 6.0 gli utenti di base conversione a VB.NET . Ha molte delle stesse caratteristiche di P / Invoke, ma la mobilitazione di alcuni tipi, in particolare le stringhe, sono molto diverse e può causare un po 'di confusione per le persone più familiari con le regole DllImport.

Non sono del tutto sicuro di quello che la documentazione allude a con la distinzione "rare". Io uso DllImport nel mio codice di frequente sia da VB.NET e C # senza alcun problema.

In generale, vorrei utilizzare DllImport oltre Dichiarare a meno che non si proviene da un 6.0 sfondo di Visual Basic. La documentazione e campioni per DllImport sono molto meglio e ci sono molti strumenti volti a generare dichiarazioni DllImport.

Altri suggerimenti

A quanto pare le istruzioni Declare e DllImport sono sostanzialmente gli stessi. È possibile utilizzare se si preferisce.

Segue una discussione dei pochi punti che possono lavorare un po 'diverso in ciascuno, che possono influenzare una preferenza per uno sopra l'altro:

Ho iniziato con un articolo da MSDN per quanto riguarda Visual Studio 2003 dal titolo Utilizzando il DllImport attributo . (Un po 'vecchio, ma dal momento che la dichiarazione DllImport sembra abbia avuto origine in .NET, è sembrato opportuno per tornare all'inizio.)

Dato un esempio dichiarazione DllImport di:

[DllImport("user32.dll", EntryPoint = "MessageBox", CharSet = Unicode)]
int MessageBox(void* hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned int uType);

Si dice che se il valore EntryPoint viene lasciato fuori, la CLR cercherà il nome della funzione (MessageBox , in questo caso) come predefinito. Tuttavia, in questo caso, dal momento che è stato specificato un set di caratteri di Unicode, il CLR sarebbe primo sguardo per una funzione chiamata "MessageBoxW" - la 'W' che indica un tipo di ritorno Unicode. (La versione ANSI tipo di ritorno sarebbe "MessageBoxA"). Se nessun "MessageBoxW" è stato trovato, allora il CLR avrebbe cercato una funzione API denominata appunto "MessageBox".

specifiche attuali sulla classe DllImportAttribute può essere trovato qui, dove ho visto la versione di .NET Framework 4: DllImportAttribute Classe

Un commento chiave nella sezione Osservazioni di questo .NET Framework 4 la pagina è che:

  

Si applica questo attributo direttamente a C # e definizioni dei metodi C ++; tuttavia, il compilatore Visual Basic emette questo attributo quando si utilizza l'istruzione Declare.

Quindi, almeno per quanto attiene alla VB.NET, il compilatore finisce con una dichiarazione Declare comunque.

C'è anche una nota importante in questa pagina:

  

Il DllImportAttribute non supporta marshalling di tipi generici.

Quindi, sembrerebbe che, se si desidera utilizzare un tipo generico, che avrebbe dovuto usare una dichiarazione Declare.

Avanti, mi dirigo verso le informazioni Declare. Una versione di Visual Studio 2010 (Visual informazioni dichiarazione di base) era qui: Istruzione Declare

Un elemento chiave qui è questa nota:

  

È possibile utilizzare solo dichiarare a livello di modulo. Questo significa che il contesto dichiarazione di un riferimento esterno deve essere una classe, struttura o modulo, e non può essere un file di origine, namespace, interfaccia, una procedura o blocco.

A quanto pare, se si desidera impostare una chiamata API al di fuori di una classe, la struttura, o un modulo, si dovrà utilizzare l'istruzione DllImport invece del Declare.

La dichiarazione esempio Declare in questa pagina:

Declare Function getUserName Lib "advapi32.dll" Alias "GetUserNameA" (
  ByVal lpBuffer As String, ByRef nSize As Integer) As Integer

A seguito di tale esempio è questo piccolo bocconcino di informazioni:

  

Il DllImportAttribute fornisce un modo alternativo di usare le funzioni di codice non gestito. L'esempio seguente dichiara una funzione importata senza l'utilizzo di un'istruzione Declare.

seguito da, ovviamente, un esempio di utilizzo DllImport.

Per quanto riguarda Unicode vs ANSI, secondo questa pagina dichiarare, se si specifica un valore CharSet (disponibile in Declare, ma non mostrato nell'esempio di cui sopra) il CLR farà lo stesso tipo di ricerca automatica nome che DllImport fa - per sia Unicode o ANSI.

Se non si specifica un valore CharSet nell'istruzione Declare, quindi è necessario assicurarsi che il nome della funzione nel Declare è lo stesso che il nome della funzione nel file di intestazione della funzione API reale, oppure è necessario specifiy un valore Alias che corrisponde al nome della funzione effettiva nel file di intestazione (come mostrato nell'esempio di cui sopra).

Io non sono riuscito a trovare alcuna documentazione di Microsoft specifica che indica che sia DllImport o dichiarare sono stati preferiti, o anche consigliato, gli uni sugli altri in ogni situazione diversa da quelle sopra indicato.

La mia conclusione, quindi, è:

1) A meno che non è necessario inserire la tua definizione in uno dei luoghi una dichiarazione Declare non può essere utilizzato, sia tecnica funzionerà bene,

e

2) se si sta utilizzando DllImport, assicuratevi di specificare il valore CharSet che si desidera (Unicode o ANSI), oppure è possibile ottenere risultati inaspettati.

A mio parere, dal momento che questa parola chiave non sembra deprected, ecc da quello che ho cercato, è sufficiente utilizzare la compilazione in tempo le parole chiave piuttosto che gli attributi.

Inoltre, quando si utilizza il Declare, non è necessario scrivere il End Function. Il vantaggio di questo è che è possibile creare un intero modulo di dichiarazioni di linea importazioni di funzione per riga, senza la necessità di pulute il codice con DllImports e End Functions.

Quando si dichiara usando la parola chiave Declare, il compilatore considera questa funzione come Shared in ogni caso, in modo che possa accedere tramite altri oggetti extenal.

Ma credo che in VB.NET corrente sono entrambi indirizzati alla stessa destinazione e nessuna differenza di prestazioni -. Alcuna garanzia su questo

Quindi, la mia conclusione è il seguente: utilizzare il Declare invece di DllImport , in particolare la lettura di ciò che lei ha citato che Microsoft ha dichiarato che dovrebbe essere utilizzato in rari casi.

Se è necessario impostare una delle seguenti opzioni, quindi utilizzare l'attributo DllImportAttribute, uso altro Declare. Da https://msdn.microsoft.com/en-us/library/w4byd5y4. aspx

  

Per applicare la BestFitMapping, CallingConvention, ExactSpelling,   PreserveSig, SetLastError o ThrowOnUnmappableChar campi a un   Microsoft Visual Basic dichiarazione del 2005, è necessario utilizzare il   DllImportAttribute attributo anziché l'istruzione Declare.

Non è chiaro dal riferimento di cui sopra solo se questo si applica solo "Visual Basic 2005" oppure no, come il riferimento di cui sopra è da un articolo di .NET 4.5. Tuttavia, ho trovato anche questo articolo ( https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute (v = vs.110) aspx ), che è specifico per la classe DllImportAttribute in .NET 4.5 :

  

il compilatore Visual Basic emette questo attributo quando si utilizza il   Dichiarare dichiarazione. Per le definizioni dei metodi complessi che includono   BestFitMapping, CallingConvention, ExactSpelling, PreserveSig,   SetLastError, o ThrowOnUnmappableChar campi, l'applicazione di questo   attribuire direttamente a definizioni dei metodi di Visual Basic .

Questo indica che l'opzione è Declare VB.net zucchero sintattico che viene convertito in DllImportAttribute in fase di compilazione, e delinea gli scenari precisi quando si utilizza DllImportAttribute direttamente è raccomandato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top