Question

Je remarque dans la documentation MSDN qu'il existe des multiples façons pour déclarer une référence à une fonction dans une DLL externe à partir d'un programme VB.NET.

La chose est source de confusion que MSDN prétend que vous ne pouvez utiliser le DllImportAttribute de classe avec des prototypes de fonction partagée" dans des cas rares «mais je ne pouvais pas trouver l'explication de cette déclaration, alors que vous pouvez simplement utiliser le Declare de mot-clé de la place.

Pourquoi ces différents, et où dois-je utiliser de façon appropriée chaque cas?

Était-ce utile?

La solution

Déclarer est vraiment une tentative de maintenir un P / Invoke syntaxe qui serait plus familier Visual Basic 6.0 utilisateurs conversion VB.NET . Il a beaucoup des mêmes caractéristiques que P / Invoke, mais le rassemblement de certains types, en particulier les chaînes, sont très différents et peut provoquer un peu de confusion pour les personnes plus familières avec les règles de DllImport.

Je ne suis pas tout à fait sûr de ce que la documentation fait allusion à la distinction « rare ». J'utilise DllImport dans mon code fréquemment à la fois VB.NET et C # sans problème.

En général, j'utiliser DllImport plus déclarer à moins que vous venez d'un Visual Basic 6.0 arrière-plan. La documentation et les échantillons pour DllImport sont beaucoup mieux et il existe de nombreux outils visant à générer des déclarations DllImport.

Autres conseils

Apparemment, les DECLARE et DllImport sont fondamentalement les mêmes. Vous pouvez utiliser celui que vous préférez.

Voici une discussion sur les quelques points qui peuvent travailler un peu différemment dans chacun, ce qui peut influencer une préférence pour l'une sur l'autre:

J'ai commencé avec un article de MSDN concernant Visual Studio 2003 intitulé aide l'attribut dllimport . (Un peu vieux, mais depuis la déclaration DllImport semble avoir son origine dans .NET, il est apparu opportun de revenir au début.)

Étant donné un exemple de déclaration DllImport:

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

Il dit que si la valeur EntryPoint est omis, le CLR recherchera le nom de la fonction (MessageBox , dans ce cas) par défaut. Cependant, dans ce cas, étant donné qu'un jeu de caractères Unicode a été spécifié, le CLR se tourneraient d'abord une fonction appelée « MessageBoxW » - l'indication « W » un type de retour Unicode. (La version de type de retour ANSI serait « MessageBoxA ».) Si aucun « MessageBoxW » n'a été trouvée, alors le CLR rechercherait une fonction API fait appelée « MessageBox ».

spécificités actuelles au sujet de la classe DllImportAttribute se trouvent ici, où je considérais la version .NET Framework 4: DllImportAttribute classe

Un commentaire clé dans la section Remarques de cette page .NET Framework 4 est que:

  

Vous appliquez cet attribut directement à C # et C ++ définitions de méthode; Cependant, le compilateur Visual Basic émet cet attribut lorsque vous utilisez l'instruction Declare.

Alors, au moins aussi se rapporte à VB.NET, le compilateur se termine par une déclaration de Declare de toute façon.

Il y a aussi une note importante dans cette page:

  

Le DllImportAttribute ne supporte pas marshaling des types génériques.

Alors, il semblerait que si vous souhaitez utiliser un type générique, vous auriez à utiliser une instruction Declare.

Ensuite, je me suis dirigé à l'information Declare. Une version de Visual Studio 2010 (info instruction Visual Basic) est ici: Declare

ici était un élément clé cette note:

  

Vous pouvez utiliser Déclarez seulement au niveau du module. Cela signifie que le contexte de déclaration pour une référence externe doit être une classe, structure ou module, et ne peut pas être un fichier source, espace de noms, interface, procédure ou bloc.

Apparemment, si vous voulez mettre en place un appel d'API en dehors d'une classe, structure ou module, vous devrez utiliser l'instruction DllImport au lieu du Declare.

La déclaration exemple Declare sur cette page:

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

Après cet exemple est cette petite friandise de l'information:

  

Le DllImportAttribute fournit une autre façon d'utiliser les fonctions dans le code non géré. L'exemple suivant déclare une fonction importée sans utiliser une instruction Declare.

suivie, bien sûr, un exemple d'utilisation DllImport.

En ce qui concerne Unicode vs les résultats ANSI, selon cette page Declare, si vous spécifiez une valeur CharSet (disponible en Declare, mais non dans l'exemple ci-dessus), le CLR fera le même type de recherche de nom automatique DllImport fait - pour soit Unicode ou ANSI.

Si vous ne spécifiez pas de valeur charset dans l'instruction Declare, alors vous devez vous assurer que votre nom de fonction dans Déclarez est le même que le nom de la fonction dans le fichier d'en-tête de la fonction API réelle, ou vous devez spécifier une valeur Alias qui correspond au nom de la fonction réelle dans le fichier d'en-tête (comme le montre l'exemple ci-dessus).

Je n'ai pas pu trouver aucune documentation Microsoft spécifique indiquant que soit DllImport ou déclarer ont été préférés, ou même recommandé, sur l'autre dans une situation autre que ceux mentionnés ci-dessus.

Ma conclusion est donc:

1) Sauf si vous devez placer votre définition dans un des lieux une déclaration de Declare ne peut pas être utilisé, que ce soit technique fonctionnera bien,

et

2) si vous utilisez DllImport, assurez-vous de spécifier la valeur que vous voulez CharSet (Unicode ou ANSI), ou vous pouvez obtenir des résultats inattendus.

À mon avis, étant donné que ce mot-clé n'a pas l'air deprected, etc. de ce que je cherchais, il suffit d'utiliser des mots-clés à la compilation plutôt que des attributs.

En outre, lorsque vous utilisez le Declare, vous n'avez pas besoin d'écrire le End Function. L'avantage de ce que vous pouvez créer un module complet de déclarations de la ligne des importations de fonction en ligne, sans avoir besoin de pulute votre code avec DllImports et End Functions.

Lorsque vous déclarez en utilisant le mot-clé Declare, les compilateur traite cette fonction Shared de toute façon, il est accessible par l'intermédiaire d'autres objets extenal.

Mais je pense que dans la VB.NET actuelle, ils sont tous deux adressés à la même cible et aucune différence de performance -. Aucune garantie sur celui-ci

Donc, ma conclusion est la suivante: Utilisez-le Declare au lieu de DllImport , en particulier la lecture ce que vous avez cité que Microsoft a déclaré qu'il devrait être utilisé dans de rares cas.

Si vous devez choisir une des options suivantes, puis utilisez l'attribut DllImportAttribute, utilisez autre Declare. De https://msdn.microsoft.com/en-us/library/w4byd5y4. aspx

  

Pour appliquer le BestFitMapping, CallingConvention, ExactSpelling,   champs PreserveSig, SetLastError ou ThrowOnUnmappableChar à un   Déclaration Microsoft Visual Basic 2005, vous devez utiliser la   DllImportAttribute attribut au lieu de l'instruction Declare.

On ne sait pas à partir de la référence ci-dessus ne s'applique à ce que « Visual Basic 2005 » ou non, comme la référence ci-dessus est d'un article 4.5 .NET. Cependant, je trouve aussi cet article (

scroll top