Funzioni esterne
Questo articolo descrive il supporto del linguaggio F# per chiamare le funzioni nel codice nativo.
Sintassi
[<DllImport( arguments )>]
extern declaration
Osservazioni:
Nella sintassi precedente, arguments
rappresenta gli argomenti forniti all'attributo System.Runtime.InteropServices.DllImportAttribute
. Il primo argomento è una stringa che rappresenta il nome della DLL che contiene questa funzione, senza l'estensione .dll. È possibile specificare argomenti aggiuntivi per qualsiasi proprietà pubblica della System.Runtime.InteropServices.DllImportAttribute
classe, ad esempio la convenzione di chiamata.
Si supponga di avere una DLL C++ nativa che contiene la funzione esportata seguente.
#include <stdio.h>
extern "C" void __declspec(dllexport) HelloWorld()
{
printf("Hello world, invoked by F#!\n");
}
È possibile chiamare questa funzione da F# usando il codice seguente.
open System.Runtime.InteropServices
module InteropWithNative =
[<DllImport(@"C:\bin\nativedll", CallingConvention = CallingConvention.Cdecl)>]
extern void HelloWorld()
InteropWithNative.HelloWorld()
L'interoperabilità con il codice nativo viene definita platform invoke ed è una funzionalità di CLR. Per altre informazioni, vedere Interoperabilità con codice non gestito. Le informazioni contenute in questa sezione sono applicabili a F#.
Definizione di parametri in funzioni esterne
Quando si dichiarano funzioni esterne con valori o parametri restituiti, si usa una sintassi simile a C. È possibile usare le dichiarazioni gestite (in cui CLR eseguirà alcune conversioni automatiche tra tipi nativi e .NET) e dichiarazioni non gestite, che potrebbero offrire prestazioni migliori in alcune circostanze. Ad esempio, la funzione Windows GetBinaryTypeW può essere dichiarata in due modi diversi:
// Using automatic marshaling of managed types
[<DllImport("kernel32.dll",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Unicode,
ExactSpelling = true)>]
extern bool GetBinaryTypeW([<MarshalAs(UnmanagedType.LPWStr)>] string lpApplicationName, uint& lpBinaryType);
MarshalAs(UnmanagedType.LPWStr)
indica a CLR di eseguire una conversione automatica tra una rappresentazione di stringa nativa .NET string
e Windows quando viene chiamata la funzione. uint&
dichiara un oggetto uint
che verrà passato byref
, ovvero, come puntatore gestito. Per ottenere un puntatore gestito, usare l'indirizzo dell'operatore &
.
In alternativa, è possibile gestire manualmente il marshalling dei tipi di dati e dichiarare le funzioni esterne usando solo tipi non gestiti.
// Using unmanaged types
[<DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)>]
extern int GetBinaryTypeW(nativeint lpApplicationName, uint* lpBinaryType);
È possibile usareMarshal.StringToHGlobalUni per convertire una stringa .NET in formato nativo e ricevere un puntatore (nativeint
) in tale stringa che potrebbe essere fornito a lpApplicationName
.
Per ottenere un puntatore a un numero intero, usare il puntatore dell'operatore &&
o la fixed
parola chiave .