> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Utilisation de plusieurs versions de l'API GameInput dans une même application

> Découvrez comment utiliser QueryInterface pour combiner différentes versions de l'API GameInput, comme v0 et v4, dans une même application.

Chaque version de l'API GameInput, de v0 à v4, définit son propre ensemble d'interfaces COM. Le runtime GameInput implémente toutes les versions sur les mêmes objets sous-jacents ; un même objet, comme un périphérique, possède donc une interface v0, une interface v4 et une interface pour chaque version intermédiaire. Pour faire passer un objet d'une version à une autre, appelez [QueryInterface](https://docs.xbox.com/fr/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface\(refiid_void\)) sur cet objet.

Cela vous permet de :

* Ajouter des fonctionnalités v4 à une application basée sur une version antérieure de l'API, comme v0, sans migrer toute l'application en une seule fois.
* Appeler des SDK, des intergiciels ou des plug-ins de moteur générés avec une version antérieure de GameInput, même lorsque le reste de votre application utilise v4.

## Versions de l'API prises en charge

Un runtime GameInput prend en charge toutes les versions de l'API inférieures ou égales à sa propre version majeure. Par exemple, lorsque le runtime GameInput 4.0 est installé, chaque objet GameInput implémente les interfaces v0, v1, v2, v3 et v4, et votre application peut en utiliser n'importe quelle combinaison.

| Runtime installé | Versions de l'API utilisables |
| - | - |
| 4.x | v0, v1, v2, v3, v4 |
| 3.x | v0, v1, v2, v3 |
| 2.x | v0, v1, v2 |
| 1.x | v0, v1 |

Si vous demandez une version de l'API plus récente que le runtime installé, `QueryInterface` et [GameInputInitialize](https://docs.xbox.com/fr/reference/input/gameinput/functions/gameinputinitialize.md) échouent avec `E_NOINTERFACE`. La version d'API la plus élevée utilisée par votre application détermine la version minimale du runtime dont elle a besoin.

Sur PC, le runtime installé est le composant redistribuable GameInput ou un runtime que vous déployez avec votre jeu. Pour plus d'informations, consultez [Package NuGet GameInput](https://docs.xbox.com/fr/build/core-features/common/input/overviews/input-nuget.md) et [Chargement indépendant de GameInput](https://docs.xbox.com/fr/build/core-features/common/input/overviews/input-agility-redistributable.md). Sur XBOX, le runtime est inclus dans le GDK, et vous pouvez également déployer un runtime plus récent avec votre jeu. Pour plus d'informations, consultez [GameInput sur les consoles XBOX](https://docs.xbox.com/fr/build/core-features/common/input/overviews/input-xbox.md).

## Configurer votre projet

Pour les nouvelles implémentations, utilisez les en-têtes et `GameInput.lib` du dernier package NuGet [Microsoft.GameInput](https://www.nuget.org/packages/Microsoft.GameInput). Dans le package, `<GameInput.h>` est l'en-tête le plus récent, et chaque en-tête antérieur se trouve dans un dossier versionné, comme `<v0/GameInput.h>` ou `<v2/GameInput.h>`. La bibliothèque exporte [GameInputInitialize](https://docs.xbox.com/fr/reference/input/gameinput/functions/gameinputinitialize.md), qui crée GameInput pour n'importe quelle version de l'API demandée.

Les bibliothèques des versions antérieures, comme celle du GDK, continuent également de fonctionner. Pour plus d'informations, consultez [Conserver une bibliothèque antérieure](#keep-an-earlier-library).

### Inclure l'en-tête v0

À partir de v1, chaque en-tête GameInput déclare ses types dans un espace de noms versionné, comme `GameInput::v4`. L'en-tête v0 déclare quant à lui ses types dans l'espace de noms global. Pour utiliser l'en-tête v0 avec l'en-tête le plus récent, placez le code réutilisable suivant dans votre propre en-tête, par exemple `GameInputV0.h` :

```cpp theme={null}
// GameInputV0.h: declares the v0 API in the GameInput::v0 namespace
#pragma once

#include <windows.h>
#include <GameInput.h>

// The v0 header isn't namespaced; its dependencies are already included above.
namespace GameInput::v0
{
    // Prevent the legacy typedefs from finding interfaces declared by the latest header.
    struct IGameInput;
    struct IGameInputReading;
    struct IGameInputDevice;
    struct IGameInputDispatcher;
    struct IGameInputForceFeedbackEffect;
    struct IGameInputRawDeviceReport;

    #include <v0/GameInput.h>
}
```

Cet en-tête fonctionne comme suit :

* Il inclut d'abord le dernier `<GameInput.h>`. Celui-ci déclare l'API la plus récente dans son propre espace de noms et inclut les en-têtes Windows et COM dont dépend l'en-tête v0, de sorte que l'en-tête v0 ne les inclut pas à nouveau dans l'espace de noms.
* Les déclarations anticipées font en sorte que les typedefs de l'en-tête v0 déclarent de nouvelles interfaces dans `GameInput::v0`, au lieu de faire référence aux interfaces déjà déclarées par l'en-tête le plus récent.
* L'inclusion de `<v0/GameInput.h>` dans l'espace de noms place chaque type, énumération et constante v0 dans `GameInput::v0`, par exemple `GameInput::v0::IGameInput` et `GameInput::v0::GameInputKindGamepad`.

Dans vos fichiers sources v0, incluez `GameInputV0.h` au lieu de `<GameInput.h>`, et ajoutez `using namespace GameInput::v0;` afin que le code existant puisse continuer à utiliser des noms non qualifiés. Tout fichier source qui inclut `GameInputV0.h` peut également utiliser l'API la plus récente avec son nom complet, par exemple `GameInput::v4::IGameInput`.

## Exemple : ajouter des fonctionnalités v4 à une application v0

Vous n'avez pas besoin de réécrire votre code v0 pour commencer à utiliser les fonctionnalités v4. Conservez le code v0 dans ses propres fichiers sources et placez le nouveau code v4 dans des fichiers sources distincts. Transmettez les objets GameInput entre les deux sous forme de `IUnknown*`, et faites en sorte que chaque côté appelle `QueryInterface` pour obtenir la version dont il a besoin.

### Code v0 existant

Le code v0 suivant crée GameInput et lit la manette. Par rapport au code v0 d'origine, seuls trois éléments changent :

* Il inclut `GameInputV0.h` au lieu de `<GameInput.h>`.
* Il crée GameInput en appelant `GameInputInitialize` avec l'IID v0, car la bibliothèque la plus récente n'exporte pas la fonction `GameInputCreate` v0.
* Il appelle le nouveau code v4 lorsque le bouton A est enfoncé.

```cpp theme={null}
// LegacyInput.cpp: existing code that uses the v0 API
#include "GameInputV0.h"

using namespace GameInput::v0;

// Implemented in NewInputFeatures.cpp.
void SetControllerColor(IUnknown* device);

IGameInput* g_gameInput = nullptr;

HRESULT InitializeInput()
{
    return GameInput::v4::GameInputInitialize(__uuidof(IGameInput), reinterpret_cast<void**>(&g_gameInput));
}

void UpdateGamepad()
{
    IGameInputReading* reading = nullptr;
    if (SUCCEEDED(g_gameInput->GetCurrentReading(GameInputKindGamepad, nullptr, &reading)))
    {
        GameInputGamepadState state;
        reading->GetGamepadState(&state);

        if (state.buttons & GameInputGamepadA)
        {
            IGameInputDevice* device = nullptr;
            reading->GetDevice(&device);
            SetControllerColor(device);
            device->Release();
        }

        reading->Release();
    }
}
```

### Nouveau code v4

Le nouveau fichier source inclut l'en-tête v4 et appelle `QueryInterface` sur le périphérique transmis par le code v0. Il modifie ensuite la couleur du voyant central de la manette avec [IGameInputDevice::SetLightingColor](https://docs.xbox.com/fr/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_setlightingcolor.md) et [IGameInputDevice::ApplyLightingColors](https://docs.xbox.com/fr/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_applylightingcolors.md), qui sont nouvelles dans v4. Si le périphérique ne dispose pas de voyant central, l'appel est ignoré.

```cpp theme={null}
// NewInputFeatures.cpp: new code that uses the v4 API
#include <windows.h>
#include <v4/GameInput.h>

using namespace GameInput::v4;

void SetControllerColor(IUnknown* legacyDevice)
{
    IGameInputDevice* device = nullptr;

    // Fails with E_NOINTERFACE if the installed runtime is older than 4.0.
    if (SUCCEEDED(legacyDevice->QueryInterface(IID_PPV_ARGS(&device))))
    {
        device->SetLightingColor({ 0, 255, 0 }, GameInputLightingGroupCenterLight);
        device->ApplyLightingColors();
        device->Release();
    }
}
```

Si `QueryInterface` échoue, le runtime installé ne prend pas en charge v4. Votre code v0 continue de fonctionner, et votre application peut ignorer les fonctionnalités v4.

Lorsque tout votre code utilise v4, vous pouvez supprimer `GameInputV0.h` et les appels à `QueryInterface`.

### Conserver une bibliothèque antérieure

Si vous continuez à lier une bibliothèque d'une version antérieure, comme celle du GDK, votre code v0 existant n'a besoin d'aucune modification. Continuez à inclure l'en-tête v0 de cette version et à appeler `GameInputCreate`. Cet appel est transféré au runtime installé ; lorsque le runtime est en version 4.0 ou ultérieure, l'objet qu'il renvoie implémente donc également les interfaces v4, et le nouveau code v4 présenté précédemment fonctionne sans modification.

Les bibliothèques antérieures n'exportent pas `GameInputInitialize`. Obtenez les interfaces v4 uniquement en appelant `QueryInterface`, et n'appelez pas la fonction `GameInputCreate` v4, qui appelle `GameInputInitialize`.

## Règles de passage d'une version à l'autre

Les interfaces des différentes versions de l'API portent les mêmes noms, comme `IGameInput` et `IGameInputDevice`, mais il s'agit de types différents dotés de méthodes différentes. Un pointeur vers une interface v0 n'est pas un pointeur vers une interface v4, même si les deux font référence au même objet.

> [!NOTE]
>
> Un cast n'équivaut pas à un appel à `QueryInterface`. Utilisez toujours `QueryInterface` pour obtenir une interface d'une autre version de l'API. N'utilisez jamais `static_cast`, `reinterpret_cast` ni un cast de style C pour convertir d'une version à l'autre. Un cast se compile, mais l'appel d'une méthode par le biais du pointeur converti peut appeler la mauvaise méthode, ce qui entraîne un comportement indéfini.

```cpp theme={null}
GameInput::v0::IGameInputDevice* legacyDevice = /* ... */;

// Wrong: compiles, but calls the wrong methods at run time.
auto badDevice = reinterpret_cast<GameInput::v4::IGameInputDevice*>(legacyDevice);

// Correct: asks the object for its v4 interface.
GameInput::v4::IGameInputDevice* device = nullptr;
HRESULT hr = legacyDevice->QueryInterface(IID_PPV_ARGS(&device));
```

Gardez également ces règles à l'esprit :

* **N'incluez pas d'autre en-tête GameInput après l'en-tête v0.** L'en-tête v0 définit ses codes d'erreur, comme `GAMEINPUT_E_DEVICE_DISCONNECTED`, sous forme de macros, et ces macros cassent les déclarations de tout en-tête GameInput inclus après lui. `GameInputV0.h` respecte cette règle en incluant d'abord l'en-tête le plus récent.
* **Les objets renvoyés utilisent la version que vous avez appelée.** Par exemple, `GetDevice` sur une lecture v4 renvoie un périphérique v4, et un rappel de périphérique inscrit auprès de l'`IGameInput` v4 reçoit des périphériques v4. Appelez `QueryInterface` avant de transmettre ces objets à du code qui utilise une autre version.
* **Chaque appel à `QueryInterface` ajoute une référence.** Libérez le pointeur renvoyé lorsque vous n'en avez plus besoin, comme pour tout autre pointeur d'interface COM.
* **Vérifiez le résultat.** Lorsque vous demandez une version plus récente de l'API, un échec signifie que le runtime installé ne prend pas en charge cette version.
* **Les types v0 de `GameInputV0.h` sont des types C++ distincts.** `GameInput::v0::IGameInput` et l'`IGameInput` global provenant de `<v0/GameInput.h>` seul décrivent la même interface, mais C++ les traite comme des types différents. Si du code existant ou une autre bibliothèque déclare des fonctions avec les types v0 globaux, appelez ces fonctions depuis un fichier source qui inclut uniquement `<v0/GameInput.h>`.

## Appeler des SDK qui utilisent une version antérieure de l'API

Certains SDK, intergiciels et plug-ins de moteur sont générés avec une version spécifique de l'API GameInput et attendent des interfaces GameInput de cette version. Votre application peut utiliser une version plus récente tout en appelant ces composants. Appelez `QueryInterface` pour obtenir la version attendue par le composant, puis transmettez ce pointeur.

Placez l'appel dans un fichier source qui inclut le même en-tête GameInput que celui utilisé par le composant. Dans l'exemple suivant, `ThirdPartySdk.h` déclare `ThirdPartySdkInitialize(GameInput::v2::IGameInput*)`, et le reste de l'application transmet son objet GameInput sous forme de `IUnknown*` :

```cpp theme={null}
// SdkBridge.cpp: calls an SDK that was built against the v2 API
#include <windows.h>
#include <v2/GameInput.h>
#include "ThirdPartySdk.h"

HRESULT InitializeThirdPartySdk(IUnknown* gameInputObject)
{
    GameInput::v2::IGameInput* gameInput = nullptr;
    HRESULT hr = gameInputObject->QueryInterface(IID_PPV_ARGS(&gameInput));
    if (SUCCEEDED(hr))
    {
        ThirdPartySdkInitialize(gameInput);
        gameInput->Release();
    }

    return hr;
}
```

La même approche fonctionne dans l'autre sens. Si un composant fournit à votre application un objet GameInput d'une version antérieure, appelez `QueryInterface` sur cet objet pour obtenir l'interface v4.

Comme toutes les versions sont implémentées par le même objet, le SDK et votre application partagent les périphériques, les lectures et l'état. La version de l'API du SDK doit également être inférieure ou égale à la version du runtime installé.

## Voir aussi

[Gestion des versions de l'API GameInput](https://docs.xbox.com/fr/build/core-features/common/input/overviews/input-versioning.md)\
[Package NuGet GameInput](https://docs.xbox.com/fr/build/core-features/common/input/overviews/input-nuget.md)\
[Chargement indépendant de GameInput](https://docs.xbox.com/fr/build/core-features/common/input/overviews/input-agility-redistributable.md)\
[GameInputInitialize](https://docs.xbox.com/fr/reference/input/gameinput/functions/gameinputinitialize.md)\
[Référence de l'API GameInput](https://docs.xbox.com/fr/reference/input/gameinput/gameinput_members.md)


## Related topics

- [Gestion des versions de l'API GameInput](https://docs.xbox.com/fr/build/core-features/common/input/overviews/input-versioning.md)
- [GameInputInitialize](https://docs.xbox.com/fr/reference/input/gameinput/functions/gameinputinitialize.md)
- [GameInput sur les consoles XBOX](https://docs.xbox.com/fr/build/core-features/common/input/overviews/input-xbox.md)
- [GameInputCreate](https://docs.xbox.com/fr/reference/input/gameinput/functions/gameinputcreate.md)
- [Portage de XInput vers GameInput](https://docs.xbox.com/fr/build/core-features/common/input/porting/input-porting-xinput.md)
