Share via


Fonctions externes

Cet article décrit la prise en charge du langage F# pour appeler des fonctions en code natif.

Syntaxe

[<DllImport( arguments )>]
extern declaration

Notes

Dans la syntaxe précédente, arguments représente les arguments fournis à l'attribut System.Runtime.InteropServices.DllImportAttribute. Le premier argument est une chaîne qui représente le nom de la DLL contenant cette fonction, sans l’extension .dll. Des arguments supplémentaires peuvent être fournis pour toutes les propriétés publiques de la classe System.Runtime.InteropServices.DllImportAttribute, comme la convention d’appel.

Supposons que vous ayez une DLL C++ native qui contient la fonction exportée suivante.

#include <stdio.h>
extern "C" void __declspec(dllexport) HelloWorld()
{
    printf("Hello world, invoked by F#!\n");
}

Vous pouvez appeler cette fonction à partir de F# en utilisant le code suivant.

open System.Runtime.InteropServices

module InteropWithNative =
    [<DllImport(@"C:\bin\nativedll", CallingConvention = CallingConvention.Cdecl)>]
    extern void HelloWorld()

InteropWithNative.HelloWorld()

L’interopérabilité avec le code natif est appelée appel de code non managé et est une fonctionnalité du CLR. Pour plus d’informations, consultez Interopération avec du code non managé. Les informations de cette section s’appliquent à F#.

Définition de paramètres dans les fonctions externes

Lorsque vous déclarez des fonctions externes avec des valeurs de retour ou des paramètres, vous utilisez une syntaxe similaire à C. Vous avez la possibilité d'utiliser les déclarations gérées (où le CLR effectuera certaines conversions automatiques entre les types natifs et .NET) et les déclarations non gérées, qui pourraient offrent de meilleures performances dans certaines circonstances. Par exemple, la fonction Windows GetBinaryTypeW peut être déclarée de deux manières différentes :

// 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) indique au CLR d’effectuer une conversion automatique entre une représentation sous forme de string .NET et de chaîne native Windows lorsque la fonction est appelée. uint& déclare un uint qui sera transmis byref, c'est-à-dire en tant que pointeur géré. Pour obtenir un pointeur géré, vous utilisez l'adresse de l'opérateur &.

Alternativement, vous souhaiterez peut-être gérer manuellement le regroupement des types de données et déclarer les fonctions externes en utilisant uniquement des types non managés.

// Using unmanaged types
[<DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)>]
extern int GetBinaryTypeW(nativeint lpApplicationName, uint* lpBinaryType);

Vous pouvez utiliserMarshal.StringToHGlobalUni pour convertir une chaîne .NET en format natif et recevoir un pointeur (nativeint) vers celui-ci qui peut être fourni à lpApplicationName.

Pour obtenir un pointeur vers un entier, utilisez le pointeur de l'opérateur && ou le mot-clé fixed.

Voir aussi