Quando si chiama le funzioni API di Windows da C #, quale fonte per le firme per la fiducia: il codice sorgente di .NET Framework o PInvoke?

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

Domanda

Ad esempio, questo è da file sorgente di .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);

e questo è da PInvoke.Net:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(HandleRef hwnd, out RECT lpRect);
  1. Qual è il corretto / migliore firma per questa funzione? (Solo uno di loro ha [return: MarshalAs(UnmanagedType.Bool)], o [In, Out] ref, ecc.)

  2. Ho notato che nei file sorgente .NET Framework molti / la maggior parte delle firme hanno ExactSpelling=true, CharSet=CharSet.Auto, ma su PInvoke non lo fanno. È questo necessario?

È stato utile?

Soluzione

Si saranno entrambi ottenere il lavoro fatto. C'è solo più di un modo per scuoiare un gatto PInvoke. In particolare per questo esempio:

  • ExactSpelling=true è un'ottimizzazione, si evita di dover la PInvoke marshaller cercando le versioni GetWindowRectA e GetWindowRectW. Non esistono per questa particolare funzione API in quanto non fa una stringa. Vedendo una differenza reale in fase di esecuzione sarebbe un miracolo.

  • CharSet=CharSet.Auto è sempre una buona idea, dato il default (ANSI) è così inefficiente. E 'appena il caso di non fare alcuna differenza qui dato che la funzione non accetta argomenti stringa.

  • [In, Out] non è necessaria, perché questo è il valore predefinito per un tipo copiabili. Una parola costoso che significa che il marshaller PInvoke può passare direttamente un puntatore alla memoria gestita, è richiesta alcuna conversione. Il più efficiente possibile. Stessa idea come CharSet se, essendo esplicito su di esso aiuta a creare il codice di auto-documentare e ricordare a che fare con il caso insolito. Essere in grado di solo [In] uso o [Out] può essere una significativa ottimizzazione, non solo qui in quanto è già ottimizzata. FWIW, [Out] sarebbe stata la scelta giusta.

  • out vs ref, stessa idea come sopra. Utilizzando out è più corretto poiché l'API non usa realtà qualsiasi passato in valori all'interno del RECT. Essa, tuttavia, non fa alcuna differenza in fase di esecuzione in quanto il compilatore JIT inizializza sempre una struttura in ogni caso.

  • [return: MarshalAs(UnmanagedType.Bool)] è inutile, è il marshalling predefinito per un BOOL di Windows. Non certo perché pinvoke.net include sempre.

Quindi, in poche parole, non è perfetto, ma entrambi funzionerà. Tali sono i rischi di PInvoke.

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