Lors de l'appel des fonctions API de Windows à partir de C #, la source pour les signatures de confiance: code source .NET Framework ou PInvoke?

StackOverflow https://stackoverflow.com/questions/4305010

Question

Par exemple, cela est du fichier source .NET Framework UnsafeNativeMethods.cs :

[DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] 
public static extern bool GetWindowRect(HandleRef hWnd, 
    [In, Out] ref NativeMethods.RECT rect);

ce qui est de PInvoke.Net:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(HandleRef hwnd, out RECT lpRect);
  1. Quelle est la bonne / meilleure signature pour cette fonction? (Un seul d'entre eux a [return: MarshalAs(UnmanagedType.Bool)] ou [In, Out] ref, etc.)

  2. Je l'ai remarqué que dans la source .NET Framework fichiers beaucoup / la plupart des signatures ont ExactSpelling=true, CharSet=CharSet.Auto, mais PInvoke ils ne le font pas. Est-ce nécessaire?

Était-ce utile?

La solution

Ils seront tous deux faire le travail. Il y a un peu plus d'une façon à la peau d'un chat PInvoke. Plus précisément pour cet exemple:

  • ExactSpelling=true est une optimisation, il évite d'avoir le PInvoke placier chercher les versions GetWindowRectA et GetWindowRectW. Ils n'existent pas pour cette fonction API particulière car il ne prend pas un argument de chaîne. En voyant une différence réelle dans le temps d'exécution serait un miracle.

  • CharSet=CharSet.Auto est toujours une bonne idée car la valeur par défaut (Ansi) est si inefficace. Il se trouve juste à ne faire aucune différence ici puisque la fonction ne prend aucun argument de chaîne.

  • [In, Out] est inutile parce que c'est la valeur par défaut pour un type blittable. Un mot coûteux qui signifie que le placier de PInvoke peut passer directement un pointeur vers la mémoire gérée, aucune conversion est nécessaire. Aussi efficace que possible. Même idée que CharSet cependant, être explicite à ce sujet aide à créer le code d'auto-documentation et de se rappeler de traiter le cas inhabituel. Être capable de ne utiliser [In] ou [Out] peut être une optimisation significative, mais pas ici, car il est déjà optimisé. FWIW, [Out] aurait été le bon choix.

  • out vs ref, même idée que ci-dessus. L'utilisation out est plus correct puisque l'API n'utilise en fait une refacturés en valeurs à l'intérieur du RECT. Il n'a pas cependant fait aucune différence lors de l'exécution depuis le compilateur JIT toujours initialise struct de toute façon.

  • [return: MarshalAs(UnmanagedType.Bool)] est inutile, il est le marshaling par défaut pour un BOOL de Windows. Je ne sais pas pourquoi pinvoke.net comprend toujours.

Donc, en un mot, ni est parfait, mais ils ont tous deux fonctionnera. Tels sont les dangers de PInvoke.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top