147 votes

Qu'est-ce qu'une poignée de fenêtre ?

Qu'est-ce qu'un "Handle" lorsqu'on parle de ressources dans Windows ? Comment fonctionnent-ils ?

158voto

Lawrence Dol Points 27976

C'est une valeur de référence abstraite à une ressource, souvent de la mémoire ou un fichier ouvert, ou un tuyau.

Correctement Dans Windows (et plus généralement en informatique), un handle est une abstraction qui cache une adresse mémoire réelle à l'utilisateur de l'API, permettant au système de réorganiser la mémoire physique de manière transparente pour le programme. La résolution d'un handle en un pointeur verrouille la mémoire, et la libération du handle invalide le pointeur. Dans ce cas, considérez-le comme un index dans une table de pointeurs... vous utilisez l'index pour les appels API du système, et le système peut modifier le pointeur dans la table à volonté.

Un pointeur réel peut également être donné comme handle lorsque le rédacteur de l'API souhaite que l'utilisateur de l'API soit isolé des spécificités de ce vers quoi pointe l'adresse renvoyée ; dans ce cas, il faut considérer que ce vers quoi pointe le handle peut changer à tout moment (d'une version à l'autre de l'API ou même d'un appel à l'autre de l'API qui renvoie le handle) - le handle doit donc être traité comme une simple valeur opaque significative. uniquement à l'API.

Je pense que je devrais ajouter que dans tout système d'exploitation moderne, même les soi-disant "vrais pointeurs" sont toujours des poignées opaques dans l'espace mémoire du processus, ce qui permet au système d'exploitation de gérer et de réorganiser la mémoire sans invalider les pointeurs dans le processus.

92voto

Dan Moulding Points 46866

A HANDLE est un identifiant unique spécifique au contexte. Par spécifique au contexte, j'entends qu'un identifiant obtenu dans un contexte donné ne peut pas nécessairement être utilisé dans un autre contexte analogue qui fonctionne également sur HANDLE s.

Par exemple, GetModuleHandle renvoie un identifiant unique pour un module actuellement chargé. Le handle retourné peut être utilisé dans d'autres fonctions qui acceptent les handles de module. Il ne peut pas être donné aux fonctions qui nécessitent d'autres types de handles. Par exemple, vous ne pouvez pas donner un handle retourné par la fonction GetModuleHandle a HeapDestroy et attendre qu'il fasse quelque chose de sensé.

El HANDLE lui-même n'est qu'un type intégral. Habituellement, mais pas nécessairement, il s'agit d'un pointeur vers un type ou un emplacement mémoire sous-jacent. Par exemple, le type HANDLE retourné par GetModuleHandle est en fait un pointeur vers l'adresse de la mémoire virtuelle de base du module. Mais il n'existe aucune règle stipulant que les handles doivent être des pointeurs. Un handle peut aussi être un simple entier (qui peut éventuellement être utilisé par certaines API Win32 comme un index dans un tableau).

HANDLE sont des représentations intentionnellement opaques qui fournissent une encapsulation et une abstraction des ressources internes de Win32. De cette façon, les API Win32 peuvent potentiellement changer le type sous-jacent derrière un HANDLE, sans que cela ait un quelconque impact sur le code utilisateur (du moins, c'est l'idée).

Considérons ces trois implémentations internes différentes d'une API Win32 que je viens d'inventer, et supposons que Widget est un struct .

Widget * GetWidget (std::string name)
{
    Widget *w;

    w = findWidget(name);

    return w;
}

void * GetWidget (std::string name)
{
    Widget *w;

    w = findWidget(name);

    return reinterpret_cast<void *>(w);
}

typedef void * HANDLE;

HANDLE GetWidget (std::string name)
{
    Widget *w;

    w = findWidget(name);

    return reinterpret_cast<HANDLE>(w);
}

Le premier exemple expose les détails internes de l'API : il permet au code utilisateur de savoir que GetWidget renvoie un pointeur vers un struct Widget . Cela a quelques conséquences :

  • le code de l'utilisateur doit avoir accès au fichier d'en-tête qui définit l'option Widget struct
  • le code de l'utilisateur pourrait potentiellement modifier les parties internes de l'appareil retourné Widget struct

Ces deux conséquences peuvent être indésirables.

Le deuxième exemple cache ce détail interne au code utilisateur, en retournant seulement void * . Le code de l'utilisateur n'a pas besoin d'accéder à l'en-tête qui définit l'élément Widget struct.

Le troisième exemple est exactement le même que le deuxième, mais nous appelons simplement la fonction void * a HANDLE à la place. Peut-être que cela décourage le code utilisateur d'essayer de comprendre exactement ce que l'on veut faire. void * pointe vers.

Pourquoi se donner tant de mal ? Considérez ce quatrième exemple d'une version plus récente de cette même API :

typedef void * HANDLE;

HANDLE GetWidget (std::string name)
{
    NewImprovedWidget *w;

    w = findImprovedWidget(name);

    return reinterpret_cast<HANDLE>(w);
}

Remarquez que l'interface de la fonction est identique à celle du troisième exemple ci-dessus. Cela signifie que le code utilisateur peut continuer à utiliser cette nouvelle version de l'API, sans aucune modification, même si l'implémentation "en coulisse" a changé pour utiliser la fonction NewImprovedWidget à la place.

Les poignées dans cet exemple ne sont en fait qu'un nouveau nom, vraisemblablement plus convivial, pour le terme void * ce qui est exactement ce qu'un HANDLE se trouve dans l'API Win32 (consultez la rubrique à MSDN ). Il fournit un mur opaque entre le code utilisateur et les représentations internes de la bibliothèque Win32 qui augmente la portabilité, entre les versions de Windows, du code qui utilise l'API Win32.

34voto

Nick Haddad Points 4326

Un HANDLE dans la programmation Win32 est un jeton qui représente une ressource gérée par le noyau Windows. Un handle peut correspondre à une fenêtre, un fichier, etc.

Les Handles sont simplement un moyen d'identifier une ressource particulaire avec laquelle vous voulez travailler en utilisant les API Win32.

Ainsi, par exemple, si vous voulez créer une fenêtre et l'afficher à l'écran, vous pouvez procéder comme suit :

// Create the window
HWND hwnd = CreateWindow(...); 
if (!hwnd)
   return; // hwnd not created

// Show the window.
ShowWindow(hwnd, SW_SHOW);

Dans l'exemple ci-dessus, HWND signifie "une poignée de fenêtre".

Si vous êtes habitué à un langage orienté objet, vous pouvez considérer un HANDLE comme une instance d'une classe sans méthodes dont l'état est uniquement modifiable par d'autres fonctions. Dans ce cas, le ShowWindow modifie l'état du HANDLE de la fenêtre.

Ver Manipulations et types de données pour plus d'informations.

8voto

sharptooth Points 93379

Un handle est un identifiant unique pour un objet géré par Windows. Il s'agit comme un pointeur mais pas un pointeur en ce sens qu'il ne s'agit pas d'une adresse qui pourrait être déréférencée par le code utilisateur pour accéder à des données. Au lieu de cela, un handle doit être transmis à un ensemble de fonctions qui peuvent effectuer des actions sur l'objet identifié par le handle.

5voto

Edwin Yip Points 1249

Un handle est comme une valeur de clé primaire d'un enregistrement dans une base de données.

edit 1 : bien, pourquoi le downvote, une clé primaire identifie de manière unique un enregistrement de base de données, et un handle dans le système Windows identifie de manière unique une fenêtre, un fichier ouvert, etc, C'est ce que je dis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X