Partager via


Exemple de wrapper d'appel de plate-forme

Mise à jour : novembre 2007

Si une structure contient des types simples, elle peut être passée à une fonction native. La routine native doit respecter la façon dont le .NET Compact Framework compresse la structure.

Considérons une fonction native appelée DoRequest qui admet un paramètre, un pointeur vers une structure. La structure définit deux champs :

  • Un tableau de caractères contenant une chaîne ANSI terminée par NULL.

  • Un entier.

Voici cette structure en C++ :

typedef struct 
{
    char *RequestName,
    int   Count,
} ALERT_REQUEST;

int DoAlertRequest(ALERT_REQUEST *pRequest);

La version managée correspondante en C# est la suivante :

struct AlertRequest
{
    String RequestName;
    int    Count;
}

class AlertClass
{
    [DLLImport("ALERT.DLL", EntryPoint="DoAlertRequest", 
        CharSet=CharacterSet.Ansi)]
    public static extern int DoRequest(ref AlertRequest Req);
}

L'attribut DllImportAttribute annote les métadonnées de l'appel de la méthode native. Il informe le Common Language Runtime que la méthode DoRequest se trouve dans ALERT.DLL, que le nom de la méthode est DoAllertRequest et que les chaînes doivent être marshalées en ANSI, car toutes les chaînes en code managé sont des chaînes Unicode.

Un appel à cette méthode en C++ sur le .NET Framework peut se présenter sous la forme suivante :

AlertRequest Request = new AlertRequest()
Request.RequestName = "beep";
Request.Count = 10;
AlertClass.DoRequest(ref Request);

Lorsque le Common Language Runtime du .NET Framework rencontre l'appel de DoRequest, il charge dynamiquement ALERT.DLL, obtient l'adresse de DoAlertRequest, construit une version non managée de la structure en convertissant les chaînes si nécessaire, exécute un push d'un pointeur vers cette structure et appelle DoAlertRequest. Il ne peut pas se contenter de passer un pointeur vers la structure parce qu'elle contient un objet String incorporé.

Étant donné ces contraintes, la méthode DoRequest native ne peut pas être appelée directement. Au lieu de cela, un appel d'un mécanisme de thunk intermédiaire doit encapsuler DoRequest. Le code C# suivant en est un exemple :

class AlertClass
{
    [DllImport("ALERT.DLL", EntryPoint="DoAlertRequestThunk")]
    private static extern int DoRequestThunk(String RequestName, int Count);

    public static int DoRequest(ref AlertRequst Req)
        {
            return DoRequestThunk(Req.RequestName, Req.Count);
        }
}

AlertClass contient toujours une méthode possédant la même signature que son homologue sur le .NET Framework. La méthode DoRequest du .NET Compact Framework est une routine managée qui appelle une routine native privée. Observez que les champs de la structure ont été décomposés en arguments séparés dans l'appel à la routine native parce que l'objet String contenu dans la structure n'est pas marshalé. Le thunk encapsule la méthode DoRequest native. Il construit une version non managée de la structure et effectue la conversion de chaîne, comme le montre le code C++ suivant :

int DoRequestThunk(wchar_t *RequestNameW, int Count)
{
    ALERT_REQUEST Req;
    int ReturnCode;
       
    // CreateAnsiFromUnicodeString allocates and builds an ANSI
    // version of the Unicode string.
    Req.RequestName = CreateAnsiFromUnicodeString(RequestNameW);
    if (Req.RequestName == NULL) 
        Return 0;

    Req.Count = Count;

    // This is the native DoRequest, not to be confused
    // with the managed method of the same name.
    ReturnCode = DoAlertRequest(&Req);

    free(Req.RequestName)
    return ReturnCode;
}

Voir aussi

Autres ressources

Prise en charge de l'appel de plate-forme (Platform Invoke)