2017-04-13 3 views
2

Lorsque j'essayais d'utiliser une déclaration P/Invoke faite dans un assembly VB.NET à partir de C#, j'ai remarqué que les arguments string devenaient des arguments ref string.Présentation de VBByRefStr dans les déclarations P/Invoke de VB.NET

Une inspection plus approfondie révèle que, par ex.

Public Declare Unicode Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueW" (_ 
    ByVal hKey As IntPtr, ByVal lpValueName As String) As UInteger 

est compilé à

[DllImport(...)]public static extern uint RegDeleteValue(
    IntPtr hKey, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpValueName); 

Sur MSDN je lis: « VBByRefStr: Une valeur qui permet Visual Basic .NET pour changer une chaîne dans le code non géré, et ont les résultats reflétés dans le code managé. Cette valeur est prise en charge uniquement pour l'invocation de la plate-forme.C'est la valeur par défaut dans les chaînes Visual Basic pour ByVal. "

Je ne comprends toujours pas. Pourquoi est-il que string lpValueName en C# (voir pinvoke.net- modifier: pour RegDeleteKey comme Damien_The_Unbeliever a souligné, la signature est la même que RegDeleteValue) mais étrange VBByRefStr en VB.NET? Devrais-je déclarer avec <MarshalAs(UnmanagedType.LPWStr)> dans VB.NET pour éviter ref en C#? Ou cela a-t-il des effets négatifs?

+0

Pas que cela fasse beaucoup de différent mais votre lien pinvoke est à une fonction * différente *. 'RegDeleteKey'! =' RegDeleteValue'. Je ne peux pas trouver une page PInvoke pour ['RegDeleteValue'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms724851 (v = vs.85) .aspx) dans advapi32 –

+0

Mon mauvais, on dirait que je me suis retrouvé avec 'RegDeleteKey' sur pinvoke quand je n'ai pas trouvé' RegDeleteValue'. Désolé pour la confusion. Cependant, l'observation principale est la même avec 'RegDeleteKey' :-) –

Répondre

3

Ceci est pour la rétrocompatibilité avec les déclarations VB6 Declare. Lors de l'utilisation de ByVal x As String, vous avez indiqué que vous vouliez convertir le type VB UTF-16 "String" en une représentation ASCII, passer un pointeur sur ce tampon ASCII à ce paramètre et, une fois l'appel réussi, convertissez le contenu de ce tampon dans la chaîne UTF-16 d'origine.

Cela a ensuite été amélioré dans VB.NET pour prendre en charge les appels d'API Unicode. Cependant, j'imagine que la constante VBByRefStr indique que le marshaling fait dans .NET doit suivre exactement la méthode dans VB6.

Si vous souhaitez le marshalling standard pour UnmanagedType.LPWStr, utilisez des attributs.

+0

Ca a du sens, merci d'expliquer! Je suppose que je devrais me débarrasser des instructions 'Declare' de style VB6 en général et utiliser' DllImport' à la place –