> ## 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.

# Uso de varias versiones de la API de GameInput en una aplicación

> Aprenda a usar QueryInterface para combinar distintas versiones de la API de GameInput, como v0 y v4, en la misma aplicación.

Cada versión de la API de GameInput, de v0 a v4, define su propio conjunto de interfaces COM. El entorno de ejecución de GameInput implementa todas las versiones en los mismos objetos subyacentes, por lo que un único objeto, como un dispositivo, tiene una interfaz v0, una interfaz v4 y una interfaz para cada versión intermedia. Para cambiar un objeto de una versión a otra, llame a [QueryInterface](https://docs.xbox.com/es/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface\(refiid_void\)) en él.

Esto le permite:

* Agregar características de v4 a una aplicación creada con una versión anterior de la API, como v0, sin migrar toda la aplicación a la vez.
* Llamar a SDK, middleware o complementos de motor que se compilaron con una versión anterior de GameInput, aunque el resto de su aplicación use v4.

## Versiones de la API compatibles

Un entorno de ejecución de GameInput admite todas las versiones de la API inferiores o iguales a su propia versión principal. Por ejemplo, con el entorno de ejecución de GameInput 4.0 instalado, cada objeto de GameInput implementa las interfaces v0, v1, v2, v3 y v4, y su aplicación puede usar cualquier combinación de ellas.

| Entorno de ejecución instalado | Versiones de la API que puede usar |
| - | - |
| 4.x | v0, v1, v2, v3, v4 |
| 3.x | v0, v1, v2, v3 |
| 2.x | v0, v1, v2 |
| 1.x | v0, v1 |

Si solicita una versión de la API más reciente que el entorno de ejecución instalado, `QueryInterface` y [GameInputInitialize](https://docs.xbox.com/es/reference/input/gameinput/functions/gameinputinitialize.md) producen un error con `E_NOINTERFACE`. La versión más alta de la API que usa su aplicación determina la versión mínima del entorno de ejecución que requiere.

En PC, el entorno de ejecución instalado es el paquete redistribuible de GameInput o un entorno de ejecución que implementa con su juego. Para obtener más información, consulte [Paquete NuGet de GameInput](https://docs.xbox.com/es/build/core-features/common/input/overviews/input-nuget.md) y [Carga local (sideloading) de GameInput](https://docs.xbox.com/es/build/core-features/common/input/overviews/input-agility-redistributable.md). En XBOX, el entorno de ejecución se incluye con el GDK, y también puede implementar un entorno de ejecución más reciente con su juego. Para obtener más información, consulte [GameInput en consolas XBOX](https://docs.xbox.com/es/build/core-features/common/input/overviews/input-xbox.md).

## Configuración del proyecto

Para las nuevas implementaciones, use los encabezados y `GameInput.lib` del paquete NuGet [Microsoft.GameInput](https://www.nuget.org/packages/Microsoft.GameInput) más reciente. En el paquete, `<GameInput.h>` es el encabezado más reciente, y cada encabezado anterior se encuentra en una carpeta con versión, como `<v0/GameInput.h>` o `<v2/GameInput.h>`. La biblioteca exporta [GameInputInitialize](https://docs.xbox.com/es/reference/input/gameinput/functions/gameinputinitialize.md), que crea GameInput para cualquier versión de la API que solicite.

Las bibliotecas de versiones anteriores, como la del GDK, también siguen funcionando. Para obtener más información, consulte [Conservar una biblioteca anterior](#keep-an-earlier-library).

### Inclusión del encabezado v0

A partir de v1, cada encabezado de GameInput declara sus tipos en un espacio de nombres con versión, como `GameInput::v4`. En cambio, el encabezado v0 declara sus tipos en el espacio de nombres global. Para usar el encabezado v0 junto con el encabezado más reciente, coloque el siguiente código reutilizable en un encabezado propio, como `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>
}
```

Este encabezado funciona de la siguiente manera:

* Primero incluye el `<GameInput.h>` más reciente. Esto declara la API más reciente en su propio espacio de nombres e incluye los encabezados de Windows y COM de los que depende el encabezado v0, de modo que el encabezado v0 no vuelve a incluirlos dentro del espacio de nombres.
* Las declaraciones adelantadas hacen que los typedef del encabezado v0 declaren nuevas interfaces en `GameInput::v0`, en lugar de hacer referencia a interfaces que el encabezado más reciente ya declaró.
* Incluir `<v0/GameInput.h>` dentro del espacio de nombres traslada cada tipo, enumeración y constante de v0 a `GameInput::v0`, como `GameInput::v0::IGameInput` y `GameInput::v0::GameInputKindGamepad`.

En sus archivos de código fuente de v0, incluya `GameInputV0.h` en lugar de `<GameInput.h>` y agregue `using namespace GameInput::v0;` para que el código existente pueda seguir usando nombres no calificados. Cualquier archivo de código fuente que incluya `GameInputV0.h` también puede usar la API más reciente mediante su nombre completo, como `GameInput::v4::IGameInput`.

## Ejemplo: agregar características de v4 a una aplicación v0

No es necesario reescribir el código v0 para empezar a usar características de v4. Mantenga el código v0 en sus propios archivos de código fuente y coloque el nuevo código v4 en archivos de código fuente independientes. Pase los objetos de GameInput entre ambos como `IUnknown*` y haga que cada parte llame a `QueryInterface` para obtener la versión que necesita.

### Código v0 existente

El siguiente código v0 crea GameInput y lee el gamepad. En comparación con el código v0 original, solo cambian tres cosas:

* Incluye `GameInputV0.h` en lugar de `<GameInput.h>`.
* Crea GameInput llamando a `GameInputInitialize` con el IID de v0, ya que la biblioteca más reciente no exporta la función `GameInputCreate` de v0.
* Llama al nuevo código v4 cuando se presiona el botón A.

```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();
    }
}
```

### Nuevo código v4

El nuevo archivo de código fuente incluye el encabezado v4 y llama a `QueryInterface` en el dispositivo que le pasa el código v0. A continuación, cambia el color de la luz central del mando con [IGameInputDevice::SetLightingColor](https://docs.xbox.com/es/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_setlightingcolor.md) e [IGameInputDevice::ApplyLightingColors](https://docs.xbox.com/es/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_applylightingcolors.md), que son nuevos en v4. Si el dispositivo no tiene luz central, la llamada se omite.

```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` produce un error, el entorno de ejecución instalado no admite v4. Su código v0 sigue funcionando y su aplicación puede omitir las características de v4.

Cuando todo su código use v4, puede quitar `GameInputV0.h` y las llamadas a `QueryInterface`.

### Conservar una biblioteca anterior

Si sigue vinculando una biblioteca de una versión anterior, como la del GDK, no es necesario cambiar en absoluto su código v0 existente. Siga incluyendo el encabezado v0 de esa versión y llamando a `GameInputCreate`. Esa llamada se reenvía al entorno de ejecución instalado, por lo que, cuando el entorno de ejecución es 4.0 o posterior, el objeto que devuelve también implementa las interfaces v4, y el nuevo código v4 mostrado anteriormente funciona sin cambios.

Las bibliotecas anteriores no exportan `GameInputInitialize`. Obtenga las interfaces v4 solo llamando a `QueryInterface`, y no llame a la función `GameInputCreate` de v4, que llama a `GameInputInitialize`.

## Reglas para cambiar entre versiones

Las interfaces de distintas versiones de la API tienen los mismos nombres, como `IGameInput` e `IGameInputDevice`, pero son tipos diferentes con métodos diferentes. Un puntero a una interfaz v0 no es un puntero a una interfaz v4, aunque ambos hagan referencia al mismo objeto.

> [!NOTE]
>
> Realizar una conversión de tipos no es lo mismo que llamar a `QueryInterface`. Use siempre `QueryInterface` para obtener una interfaz de otra versión de la API. Nunca use `static_cast`, `reinterpret_cast` ni una conversión de estilo C para convertir entre versiones. Una conversión se compila, pero llamar a un método a través del puntero convertido puede llamar al método incorrecto, lo que provoca un comportamiento indefinido.

```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));
```

Tenga en cuenta también estas reglas:

* **No incluya otro encabezado de GameInput después del encabezado v0.** El encabezado v0 define sus códigos de error, como `GAMEINPUT_E_DEVICE_DISCONNECTED`, como macros, y esas macros rompen las declaraciones de cualquier encabezado de GameInput que se incluya después. `GameInputV0.h` sigue esta regla al incluir primero el encabezado más reciente.
* **Los objetos devueltos usan la versión a la que llamó.** Por ejemplo, `GetDevice` en una lectura v4 devuelve un dispositivo v4, y una devolución de llamada de dispositivo registrada con la interfaz `IGameInput` de v4 recibe dispositivos v4. Llame a `QueryInterface` antes de pasar estos objetos a código que use otra versión.
* **Cada llamada a `QueryInterface` agrega una referencia.** Libere el puntero devuelto cuando ya no lo necesite, igual que cualquier otro puntero de interfaz COM.
* **Compruebe el resultado.** Cuando solicita una versión más reciente de la API, un error significa que el entorno de ejecución instalado no admite esa versión.
* **Los tipos v0 de `GameInputV0.h` son tipos de C++ independientes.** `GameInput::v0::IGameInput` y la interfaz global `IGameInput` de `<v0/GameInput.h>` por sí solo describen la misma interfaz, pero C++ los trata como tipos diferentes. Si el código existente u otra biblioteca declara funciones con los tipos v0 globales, llame a esas funciones desde un archivo de código fuente que incluya solo `<v0/GameInput.h>`.

## Llamar a SDK que usan una versión anterior de la API

Algunos SDK, middleware y complementos de motor se compilan con una versión específica de la API de GameInput y esperan interfaces de GameInput de esa versión. Su aplicación puede usar una versión más reciente y seguir llamando a estos componentes. Llame a `QueryInterface` para obtener la versión que espera el componente y pase ese puntero.

Coloque la llamada en un archivo de código fuente que incluya el mismo encabezado de GameInput que usa el componente. En el siguiente ejemplo, `ThirdPartySdk.h` declara `ThirdPartySdkInitialize(GameInput::v2::IGameInput*)`, y el resto de la aplicación pasa su objeto de GameInput como `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;
}
```

El mismo enfoque funciona en la dirección contraria. Si un componente proporciona a su aplicación un objeto de GameInput de una versión anterior, llame a `QueryInterface` en él para obtener la interfaz v4.

Como todas las versiones las implementa el mismo objeto, el SDK y su aplicación comparten dispositivos, lecturas y estado. La versión de la API del SDK también debe ser inferior o igual a la versión del entorno de ejecución instalado.

## Consulte también

[Control de versiones de la API de GameInput](https://docs.xbox.com/es/build/core-features/common/input/overviews/input-versioning.md)\
[Paquete NuGet de GameInput](https://docs.xbox.com/es/build/core-features/common/input/overviews/input-nuget.md)\
[Carga local (sideloading) de GameInput](https://docs.xbox.com/es/build/core-features/common/input/overviews/input-agility-redistributable.md)\
[GameInputInitialize](https://docs.xbox.com/es/reference/input/gameinput/functions/gameinputinitialize.md)\
[Referencia de la API de GameInput](https://docs.xbox.com/es/reference/input/gameinput/gameinput_members.md)


## Related topics

- [Control de versiones de la API de GameInput](https://docs.xbox.com/es/build/core-features/common/input/overviews/input-versioning.md)
- [GameInput en consolas XBOX](https://docs.xbox.com/es/build/core-features/common/input/overviews/input-xbox.md)
- [GameInputInitialize](https://docs.xbox.com/es/reference/input/gameinput/functions/gameinputinitialize.md)
- [GameInputCreate](https://docs.xbox.com/es/reference/input/gameinput/functions/gameinputcreate.md)
- [Miembros de la API de GameInput](https://docs.xbox.com/es/reference/input/gameinput/gameinput_members.md)
